Wishlist: Planning travel in a SwiftUI app
At a glance
| Item | Summary |
|---|---|
| Purpose | Build a travel planning app that organizes trips into collections and tracks activity completion. |
| App architecture | A Swift sample bundle with entry-bearing project variants WithSwiftData, WithoutPersistence, each leading to SwiftUI APIs. |
| Main patterns | Delegate or data-source callbacks, Binding-based state propagation |
| Project style | 43 scanned source file(s) across Swift, organized around ranked entry, type, and file boundaries. |
Project structure
Source bundle/
├── WithSwiftData/
│ └── Wishlist/
│ ├── WishlistApp.swift
│ └── Views/
│ ├── Trips/
│ │ ├── AddTripView.swift
│ │ └── TripCollectionView.swift
│ ├── SearchView.swift
│ └── Goals/
│ └── GoalsView.swift
└── WithoutPersistence/
└── Wishlist/
├── WishlistApp.swift
├── Views/
│ ├── Trips/
│ │ ├── AddTripView.swift
│ │ └── TripCollectionView.swift
│ ├── SearchView.swift
│ └── Goals/
│ └── GoalsView.swift
└── Models/
├── DataSource.swift
└── TripEditModel.swift
Structure observations
- Architecturally prominent files are ranked from entry points and role-named declarations; resource-only paths are omitted.
- Primary languages: Swift.
- The verified tree contains 7 project/configuration file(s) and 84 source declaration(s).
Overall architecture
flowchart LR
Bundle["Sample bundle"]
V1["WithSwiftData"]
V2["WithoutPersistence"]
Boundary["SwiftUI APIs"]
Bundle --> V1
V1 --> Boundary
Bundle --> V2
V2 --> Boundary
Reference code
WithSwiftData/Wishlist/WishlistApp.swift:11 — architecture anchor
@main
struct WishlistApp: App {
// ...
}Interpretation
The branches represent separate entry-bearing project variants in the downloaded bundle, not runtime calls between those variants. Each branch is intentionally collapsed at the documented framework boundary; the detailed target-local flow remains in the cited files. Ownership is claimed only where the next section cites a stored property or assignment.
Ownership and state
classDiagram
SearchResultsListView *-- Array : trips
SearchResultsListView *-- Array : activities
SearchResultsListView *-- String : searchText
SearchResultsListView o-- ID : namespace
Ownership evidence
WithSwiftData/Wishlist/Views/SearchView.swift:52 — stored dependency or nearest verified ownership anchor
private struct SearchResultsListView: View {
// ...
@Query(sort: \Trip.name) private var trips: [Trip]
// ...
}| Owner | Object or state | Relationship | Mutation authority |
|---|---|---|---|
SearchResultsListView |
Array (trips) |
owns value state | Owning lexical scope |
SearchResultsListView |
Array (activities) |
owns value state | Owning lexical scope |
SearchResultsListView |
String (searchText) |
owns value state | App/module collaborators |
SearchResultsListView |
ID (namespace) |
stores or receives | App/module collaborators |
Composition arrows indicate a source-visible construction expression or locally owned value state; aggregation means the owner stores or receives a dependency without proving exclusive lifetime ownership.
Class and protocol design
WithSwiftData/Wishlist/WishlistApp.swift:12 — representative type boundary
struct WishlistApp: App {
// ...
}| Type | Responsibility | Depends on or conforms to |
|---|---|---|
WishlistApp |
Application entry and top-level composition | App |
WishlistApp |
Application entry and top-level composition | App |
AddTripView |
User-interface presentation and input forwarding | View |
Model |
Feature data or observable state | Concrete collaborators/imported frameworks |
AddTripView |
User-interface presentation and input forwarding | View |
Model |
Feature data or observable state | Concrete collaborators/imported frameworks |
SearchView |
User-interface presentation and input forwarding | View |
SearchResultsListView |
User-interface presentation and input forwarding | View |
SearchItemView |
User-interface presentation and input forwarding | View |
TripSearchSectionView |
User-interface presentation and input forwarding | View |
No local protocol conformance is claimed as protocol-oriented design; external framework conformances are listed only as dependencies.
Access control
| Symbol | Access | Verified effect | Likely rationale |
|---|---|---|---|
ordinalModifier (WithSwiftData/Wishlist/Models/Goal.swift:56) |
fileprivate |
Use is restricted to this source file. | Inference: share with same-file helpers or extensions without exposing the symbol module-wide. |
allTrips (WithSwiftData/Wishlist/Models/SampleData.swift:58) |
private |
Use is restricted to the lexical declaration and same-file extensions allowed by Swift. | Inference: keep state mutation or dependency lifetime inside the owning implementation. |
allTripGoals (WithSwiftData/Wishlist/Models/SampleData.swift:182) |
private |
Use is restricted to the lexical declaration and same-file extensions allowed by Swift. | Inference: keep state mutation or dependency lifetime inside the owning implementation. |
allActivityGoals (WithSwiftData/Wishlist/Models/SampleData.swift:200) |
private |
Use is restricted to the lexical declaration and same-file extensions allowed by Swift. | Inference: keep state mutation or dependency lifetime inside the owning implementation. |
Reference code
WithSwiftData/Wishlist/Models/Goal.swift:56 — representative boundary
fileprivate var ordinalModifier: String {
target == 1 ? "first" : "\(target.ordinal)"
}Swift declarations without a modifier are internal; explicit private, fileprivate, private(set), public, or open entries above are interpreted by language semantics. Objective-C/C samples instead rely on header and implementation boundaries, which are not equivalent to Swift lexical privacy.
Logic ownership and placement
| Logic | Owning type or file | Placement rationale |
|---|---|---|
| Application entry and top-level composition | WishlistApp |
The source’s App suffix makes this role explicit. |
| Supplies data through a callback contract | DataSource |
The source’s DataSource suffix makes this role explicit. |
| Feature data or observable state | Model, TripEditModel |
The source’s Model suffix makes this role explicit. |
| User-interface presentation and input forwarding | ActivityItemView, ActivityProgressView, ActivitySearchSectionView, AddTripView |
The source’s View suffix makes this role explicit. |
Design patterns
| Pattern | Source evidence | Purpose or tradeoff |
|---|---|---|
| Delegate or data-source callbacks | WithoutPersistence/Wishlist/Models/DataSource.swift:16 |
Callback protocols invert event delivery back into the sample’s owner. |
| Binding-based state propagation | WithSwiftData/Wishlist/Views/Trips/ActivitySection.swift:15 |
A binding exposes controlled read/write access while the upstream owner remains authoritative. |
Naming conventions
- Types: App: WishlistApp; DataSource: DataSource; Model: Model, TripEditModel; View: ActivityItemView, ActivityProgressView, ActivitySearchSectionView, AddTripView, ContentView.
- Protocols: no local protocol declaration in the scanned source.
- Methods:
saveImageToTemporaryDirectory,addTrip. - Files:
WithSwiftData/Wishlist/WishlistApp.swift,WithoutPersistence/Wishlist/WishlistApp.swift,WithSwiftData/Wishlist/Views/Trips/AddTripView.swift,WithoutPersistence/Wishlist/Views/Trips/AddTripView.swift,WithSwiftData/Wishlist/Views/SearchView.swift,WithoutPersistence/Wishlist/Views/SearchView.swift.
Architecture takeaways
WishlistAppis the main source-visible entry or composition anchor for this sample.- Framework work reaches SwiftUI, SwiftData, PhotosUI, UIKit through a deliberately small high-level chain; the detailed API graph remains inside the cited implementation files.
- Stored-property evidence identifies lifecycle collaboration; it does not by itself prove exclusive object ownership.
- Access-control conclusions separate verified language visibility from the likely design rationale.
- The source does not justify labeling the design protocol-oriented.
Source map
| Source file | Relevant symbols |
|---|---|
WithSwiftData/Wishlist/WishlistApp.swift |
WishlistApp |
WithoutPersistence/Wishlist/WishlistApp.swift |
WishlistApp |
WithSwiftData/Wishlist/Views/Trips/AddTripView.swift |
AddTripView, TripImagePicker, TripDetailsForm, TripTitleField, TripGroupPicker, Model |
WithoutPersistence/Wishlist/Views/Trips/AddTripView.swift |
AddTripView, TripImagePicker, TripDetailsForm, TripTitleField, TripGroupPicker, Model |
WithSwiftData/Wishlist/Views/SearchView.swift |
SearchView, SearchResultsListView, SearchItemView, TripSearchSectionView, ActivitySearchSectionView |
WithoutPersistence/Wishlist/Views/SearchView.swift |
SearchView, SearchResultsListView, SearchSection, SearchItemView, SearchSectionView |
WithSwiftData/Wishlist/Views/Goals/GoalsView.swift |
GoalsView, AchievedGoalTile, GoalTile |
WithSwiftData/Wishlist/Views/Trips/TripCollectionView.swift |
TripCollectionView, TripCard, Size |
WithoutPersistence/Wishlist/Views/Goals/GoalsView.swift |
GoalsView, AchievedGoalTile, GoalTile |
WithoutPersistence/Wishlist/Views/Trips/TripCollectionView.swift |
TripCollectionView, TripCard, Size |