From 682b0e670c4be9c0486ea1cbc6379c34e153366f Mon Sep 17 00:00:00 2001
From: Daniel Tull
Date: Wed, 5 Jun 2019 10:31:00 -0700
Subject: [PATCH 1/2] Work through 2nd tutorial
---
.../project.pbxproj | 13 +++++--
.../Landmarks/Landmarks/LandmarkDetail.swift | 15 ++++----
.../Landmarks/Landmarks/LandmarkList.swift | 33 ++++++++++++++++++
.../Landmarks/Landmarks/LandmarkRow.swift | 34 +++++++++++++++++++
.../Landmarks/Landmarks/Models/Landmark.swift | 2 +-
.../Landmarks/Landmarks/SceneDelegate.swift | 2 +-
.../Supporting Views/CircleImage.swift | 7 ++--
.../Landmarks/Supporting Views/MapView.swift | 8 +++--
8 files changed, 98 insertions(+), 16 deletions(-)
create mode 100644 2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/LandmarkList.swift
create mode 100644 2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/LandmarkRow.swift
diff --git a/2 Building Lists and Navigation/StartingPoint/Landmarks/BuildingListsAndNavigation.xcodeproj/project.pbxproj b/2 Building Lists and Navigation/StartingPoint/Landmarks/BuildingListsAndNavigation.xcodeproj/project.pbxproj
index 4d4bd47..1788611 100644
--- a/2 Building Lists and Navigation/StartingPoint/Landmarks/BuildingListsAndNavigation.xcodeproj/project.pbxproj
+++ b/2 Building Lists and Navigation/StartingPoint/Landmarks/BuildingListsAndNavigation.xcodeproj/project.pbxproj
@@ -7,6 +7,8 @@
objects = {
/* Begin PBXBuildFile section */
+ 24FEC89922A770D800B58A9D /* LandmarkRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24FEC89822A770D800B58A9D /* LandmarkRow.swift */; };
+ 24FEC89B22A775AB00B58A9D /* LandmarkList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24FEC89A22A775AB00B58A9D /* LandmarkList.swift */; };
B7394866229F194000C47603 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7394865229F194000C47603 /* AppDelegate.swift */; };
B7394868229F194000C47603 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7394867229F194000C47603 /* SceneDelegate.swift */; };
B739486A229F194000C47603 /* LandmarkDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7394869229F194000C47603 /* LandmarkDetail.swift */; };
@@ -33,6 +35,8 @@
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
+ 24FEC89822A770D800B58A9D /* LandmarkRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LandmarkRow.swift; sourceTree = ""; };
+ 24FEC89A22A775AB00B58A9D /* LandmarkList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LandmarkList.swift; sourceTree = ""; };
B7394862229F194000C47603 /* Landmarks.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Landmarks.app; sourceTree = BUILT_PRODUCTS_DIR; };
B7394865229F194000C47603 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
B7394867229F194000C47603 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; };
@@ -59,8 +63,8 @@
B739488F229F292F00C47603 /* chincoteague.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = chincoteague.jpg; sourceTree = ""; };
B7394890229F292F00C47603 /* chilkoottrail.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = chilkoottrail.jpg; sourceTree = ""; };
C4E4AAA0C4E4035000000001 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; };
- F4750E80F475342000000001 /* SampleCode.xcconfig */ = {isa = PBXFileReference; name = SampleCode.xcconfig; path = ../Configuration/SampleCode.xcconfig; sourceTree = ""; };
- F479D5A0F479BCB000000001 /* LICENSE.txt */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE.txt; sourceTree = ""; };
+ F4750E80F475342000000001 /* SampleCode.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = SampleCode.xcconfig; path = ../Configuration/SampleCode.xcconfig; sourceTree = ""; };
+ F479D5A0F479BCB000000001 /* LICENSE.txt */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = LICENSE.txt; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -100,6 +104,8 @@
B7394865229F194000C47603 /* AppDelegate.swift */,
B7394867229F194000C47603 /* SceneDelegate.swift */,
B7394869229F194000C47603 /* LandmarkDetail.swift */,
+ 24FEC89822A770D800B58A9D /* LandmarkRow.swift */,
+ 24FEC89A22A775AB00B58A9D /* LandmarkList.swift */,
B739487D229F1C0100C47603 /* Supporting Views */,
B7394883229F291A00C47603 /* Resources */,
B739486B229F194200C47603 /* Assets.xcassets */,
@@ -183,7 +189,6 @@
B739485E229F194000C47603 /* Sources */,
B739485F229F194000C47603 /* Frameworks */,
B7394860229F194000C47603 /* Resources */,
- C602AC70C605937000000001,
);
buildRules = (
);
@@ -262,8 +267,10 @@
B7394866229F194000C47603 /* AppDelegate.swift in Sources */,
B739487A229F1B3F00C47603 /* CircleImage.swift in Sources */,
B739487C229F1B6800C47603 /* MapView.swift in Sources */,
+ 24FEC89B22A775AB00B58A9D /* LandmarkList.swift in Sources */,
B7394868229F194000C47603 /* SceneDelegate.swift in Sources */,
B739486A229F194000C47603 /* LandmarkDetail.swift in Sources */,
+ 24FEC89922A770D800B58A9D /* LandmarkRow.swift in Sources */,
B7394881229F28B900C47603 /* Landmark.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
diff --git a/2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/LandmarkDetail.swift b/2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/LandmarkDetail.swift
index ee34bba..55477a8 100644
--- a/2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/LandmarkDetail.swift
+++ b/2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/LandmarkDetail.swift
@@ -8,24 +8,27 @@ A view showing the details for a landmark.
import SwiftUI
struct LandmarkDetail: View {
+
+ var landmark: Landmark
+
var body: some View {
VStack {
- MapView()
+ MapView(coordinate: landmark.locationCoordinate)
.edgesIgnoringSafeArea(.top)
.frame(height: 300)
- CircleImage()
+ CircleImage(image: landmark.image(forSize: 250))
.offset(x: 0, y: -130)
.padding(.bottom, -130)
VStack(alignment: .leading) {
- Text("Turtle Rock")
+ Text(landmark.name)
.font(.title)
HStack(alignment: .top) {
- Text("Joshua Tree National Park")
+ Text(landmark.park)
.font(.subheadline)
Spacer()
- Text("California")
+ Text(landmark.state)
.font(.subheadline)
}
}
@@ -39,7 +42,7 @@ struct LandmarkDetail: View {
#if DEBUG
struct LandmarkDetail_Previews: PreviewProvider {
static var previews: some View {
- LandmarkDetail()
+ LandmarkDetail(landmark: landmarkData[0])
}
}
#endif
diff --git a/2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/LandmarkList.swift b/2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/LandmarkList.swift
new file mode 100644
index 0000000..30c4c41
--- /dev/null
+++ b/2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/LandmarkList.swift
@@ -0,0 +1,33 @@
+//
+// LandmarkList.swift
+// Landmarks
+//
+// Created by Daniel Tull on 04/06/2019.
+// Copyright © 2019 Apple. All rights reserved.
+//
+
+import SwiftUI
+
+struct LandmarkList : View {
+ var body: some View {
+ NavigationView {
+ List(landmarkData) { landmark in
+ NavigationButton(destination: LandmarkDetail(landmark: landmark)) {
+ LandmarkRow(landmark: landmark)
+ }
+ }
+ }
+ .navigationBarTitle(Text("Landmarks"))
+ }
+}
+
+#if DEBUG
+struct LandmarkList_Previews : PreviewProvider {
+ static var previews: some View {
+ ForEach(["iPhone SE", "iPhone XS Max"].identified(by: \.self)) { device in
+ LandmarkList()
+ .previewDevice(PreviewDevice(rawValue: device))
+ }
+ }
+}
+#endif
diff --git a/2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/LandmarkRow.swift b/2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/LandmarkRow.swift
new file mode 100644
index 0000000..bb97cb6
--- /dev/null
+++ b/2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/LandmarkRow.swift
@@ -0,0 +1,34 @@
+//
+// LandmarkRow.swift
+// Landmarks
+//
+// Created by Daniel Tull on 04/06/2019.
+// Copyright © 2019 Apple. All rights reserved.
+//
+
+import SwiftUI
+
+struct LandmarkRow : View {
+
+ var landmark: Landmark
+
+ var body: some View {
+ HStack {
+ landmark.image(forSize: 50)
+ Text(landmark.name)
+ Spacer()
+ }
+ }
+}
+
+#if DEBUG
+struct LandmarkRow_Previews : PreviewProvider {
+ static var previews: some View {
+ Group {
+ LandmarkRow(landmark: landmarkData[0])
+ LandmarkRow(landmark: landmarkData[1])
+ }
+ .previewLayout(.fixed(width: 300, height: 70))
+ }
+}
+#endif
diff --git a/2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/Models/Landmark.swift b/2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/Models/Landmark.swift
index 31c85e1..3832625 100644
--- a/2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/Models/Landmark.swift
+++ b/2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/Models/Landmark.swift
@@ -8,7 +8,7 @@ The model for an individual landmark.
import SwiftUI
import CoreLocation
-struct Landmark: Hashable, Codable {
+struct Landmark: Hashable, Identifiable, Codable {
var id: Int
var name: String
fileprivate var imageName: String
diff --git a/2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/SceneDelegate.swift b/2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/SceneDelegate.swift
index f7316e2..c4d69a9 100644
--- a/2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/SceneDelegate.swift
+++ b/2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/SceneDelegate.swift
@@ -19,7 +19,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
// Use a UIHostingController as window root view controller
let window = UIWindow(frame: UIScreen.main.bounds)
- window.rootViewController = UIHostingController(rootView: LandmarkDetail())
+ window.rootViewController = UIHostingController(rootView: LandmarkList())
self.window = window
window.makeKeyAndVisible()
}
diff --git a/2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/Supporting Views/CircleImage.swift b/2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/Supporting Views/CircleImage.swift
index f32a333..98bd278 100644
--- a/2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/Supporting Views/CircleImage.swift
+++ b/2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/Supporting Views/CircleImage.swift
@@ -8,8 +8,11 @@ A view that clips an image to a circle and adds a stroke and shadow.
import SwiftUI
struct CircleImage: View {
+
+ var image: Image
+
var body: some View {
- Image("turtlerock")
+ image
.clipShape(Circle())
.overlay(
Circle().stroke(Color.white, lineWidth: 4))
@@ -20,7 +23,7 @@ struct CircleImage: View {
#if DEBUG
struct CircleImage_Previews: PreviewProvider {
static var previews: some View {
- CircleImage()
+ CircleImage(image: Image("turtlerock"))
}
}
#endif
diff --git a/2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/Supporting Views/MapView.swift b/2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/Supporting Views/MapView.swift
index ea5716e..953d5ce 100644
--- a/2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/Supporting Views/MapView.swift
+++ b/2 Building Lists and Navigation/StartingPoint/Landmarks/Landmarks/Supporting Views/MapView.swift
@@ -9,13 +9,14 @@ import SwiftUI
import MapKit
struct MapView: UIViewRepresentable {
+
+ var coordinate: CLLocationCoordinate2D
+
func makeUIView(context: Context) -> MKMapView {
MKMapView(frame: .zero)
}
func updateUIView(_ view: MKMapView, context: Context) {
- let coordinate = CLLocationCoordinate2D(
- latitude: 34.011_286, longitude: -116.166_868)
let span = MKCoordinateSpan(latitudeDelta: 2.0, longitudeDelta: 2.0)
let region = MKCoordinateRegion(center: coordinate, span: span)
view.setRegion(region, animated: true)
@@ -25,7 +26,8 @@ struct MapView: UIViewRepresentable {
#if DEBUG
struct MapView_Previews: PreviewProvider {
static var previews: some View {
- MapView()
+ MapView(coordinate: CLLocationCoordinate2D(
+ latitude: 34.011_286, longitude: -116.166_868))
}
}
#endif
From f1c1e19db34fa29870b4dff6d39d4159b081545c Mon Sep 17 00:00:00 2001
From: Daniel Tull
Date: Wed, 5 Jun 2019 10:31:08 -0700
Subject: [PATCH 2/2] Work through 3rd tutorial
---
.../project.pbxproj | 9 +++++---
.../Landmarks/Landmarks/LandmarkDetail.swift | 23 +++++++++++++++++--
.../Landmarks/Landmarks/LandmarkList.swift | 23 ++++++++++++-------
.../Supporting Views/LandmarkRow.swift | 6 +++++
.../Landmarks/Landmarks/UserData.swift | 16 +++++++++++++
5 files changed, 64 insertions(+), 13 deletions(-)
create mode 100644 3 Handling User Input/StartingPoint/Landmarks/Landmarks/UserData.swift
diff --git a/3 Handling User Input/StartingPoint/Landmarks/HandlingUserInput.xcodeproj/project.pbxproj b/3 Handling User Input/StartingPoint/Landmarks/HandlingUserInput.xcodeproj/project.pbxproj
index 60294c7..bd382f2 100644
--- a/3 Handling User Input/StartingPoint/Landmarks/HandlingUserInput.xcodeproj/project.pbxproj
+++ b/3 Handling User Input/StartingPoint/Landmarks/HandlingUserInput.xcodeproj/project.pbxproj
@@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
+ 24FEC89D22A7813C00B58A9D /* UserData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24FEC89C22A7813C00B58A9D /* UserData.swift */; };
B7394866229F194000C47603 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7394865229F194000C47603 /* AppDelegate.swift */; };
B7394868229F194000C47603 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7394867229F194000C47603 /* SceneDelegate.swift */; };
B739486A229F194000C47603 /* LandmarkDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7394869229F194000C47603 /* LandmarkDetail.swift */; };
@@ -35,8 +36,9 @@
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
- 8679DA608679DDE000000001 /* SampleCode.xcconfig */ = {isa = PBXFileReference; name = SampleCode.xcconfig; path = ../Configuration/SampleCode.xcconfig; sourceTree = ""; };
- 867DE190867CBB1000000001 /* LICENSE.txt */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE.txt; sourceTree = ""; };
+ 24FEC89C22A7813C00B58A9D /* UserData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserData.swift; sourceTree = ""; };
+ 8679DA608679DDE000000001 /* SampleCode.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = SampleCode.xcconfig; path = ../Configuration/SampleCode.xcconfig; sourceTree = ""; };
+ 867DE190867CBB1000000001 /* LICENSE.txt */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = LICENSE.txt; sourceTree = ""; };
B7394862229F194000C47603 /* Landmarks.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Landmarks.app; sourceTree = BUILT_PRODUCTS_DIR; };
B7394865229F194000C47603 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
B7394867229F194000C47603 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; };
@@ -123,6 +125,7 @@
B73948A0229F2E1F00C47603 /* LandmarkList.swift */,
B739489E229F2D9700C47603 /* LandmarkRow.swift */,
B7394869229F194000C47603 /* LandmarkDetail.swift */,
+ 24FEC89C22A7813C00B58A9D /* UserData.swift */,
B739487D229F1C0100C47603 /* Supporting Views */,
B7394883229F291A00C47603 /* Resources */,
B739486B229F194200C47603 /* Assets.xcassets */,
@@ -189,7 +192,6 @@
B739485E229F194000C47603 /* Sources */,
B739485F229F194000C47603 /* Frameworks */,
B7394860229F194000C47603 /* Resources */,
- C602AC70C605937000000001,
);
buildRules = (
);
@@ -272,6 +274,7 @@
B7394868229F194000C47603 /* SceneDelegate.swift in Sources */,
B739486A229F194000C47603 /* LandmarkDetail.swift in Sources */,
B739489F229F2D9700C47603 /* LandmarkRow.swift in Sources */,
+ 24FEC89D22A7813C00B58A9D /* UserData.swift in Sources */,
B7394881229F28B900C47603 /* Landmark.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
diff --git a/3 Handling User Input/StartingPoint/Landmarks/Landmarks/LandmarkDetail.swift b/3 Handling User Input/StartingPoint/Landmarks/Landmarks/LandmarkDetail.swift
index e957172..e5356ca 100644
--- a/3 Handling User Input/StartingPoint/Landmarks/Landmarks/LandmarkDetail.swift
+++ b/3 Handling User Input/StartingPoint/Landmarks/Landmarks/LandmarkDetail.swift
@@ -8,7 +8,11 @@ A view showing the details for a landmark.
import SwiftUI
struct LandmarkDetail: View {
+ @EnvironmentObject var userData: UserData
var landmark: Landmark
+ var landmarkIndex: Int {
+ userData.landmarks.firstIndex(where: { $0.id == landmark.id })!
+ }
var body: some View {
VStack {
@@ -20,8 +24,22 @@ struct LandmarkDetail: View {
.padding(.bottom, -130)
VStack(alignment: .leading) {
- Text(landmark.name)
- .font(.title)
+ HStack {
+ Text(landmark.name)
+ .font(.title)
+
+ Button(action: {
+ self.userData.landmarks[self.landmarkIndex].isFavorite.toggle()
+ }) {
+ if self.userData.landmarks[self.landmarkIndex].isFavorite {
+ Image(systemName: "star.fill")
+ .foregroundColor(.yellow)
+ } else {
+ Image(systemName: "star")
+ .foregroundColor(.gray)
+ }
+ }
+ }
HStack(alignment: .top) {
Text(landmark.park)
@@ -43,6 +61,7 @@ struct LandmarkDetail: View {
struct LandmarkDetail_Previews: PreviewProvider {
static var previews: some View {
LandmarkDetail(landmark: landmarkData[0])
+ .environmentObject(UserData())
}
}
#endif
diff --git a/3 Handling User Input/StartingPoint/Landmarks/Landmarks/LandmarkList.swift b/3 Handling User Input/StartingPoint/Landmarks/Landmarks/LandmarkList.swift
index 1c5b7ee..9ca5fa6 100644
--- a/3 Handling User Input/StartingPoint/Landmarks/Landmarks/LandmarkList.swift
+++ b/3 Handling User Input/StartingPoint/Landmarks/Landmarks/LandmarkList.swift
@@ -8,11 +8,21 @@ A view showing a list of landmarks.
import SwiftUI
struct LandmarkList: View {
+
+ @EnvironmentObject var userData: UserData
+
var body: some View {
NavigationView {
- List(landmarkData) { landmark in
- NavigationButton(destination: LandmarkDetail(landmark: landmark)) {
- LandmarkRow(landmark: landmark)
+ List {
+ Toggle(isOn: $userData.showFavoritesOnly) {
+ Text("Show Favorites Only")
+ }
+ ForEach(self.userData.landmarks) { landmark in
+ if !self.userData.showFavoritesOnly || landmark.isFavorite {
+ NavigationButton(destination: LandmarkDetail(landmark: landmark)) {
+ LandmarkRow(landmark: landmark)
+ }
+ }
}
}
.navigationBarTitle(Text("Landmarks"), displayMode: .large)
@@ -23,11 +33,8 @@ struct LandmarkList: View {
#if DEBUG
struct LandmarkList_Previews: PreviewProvider {
static var previews: some View {
- ForEach(["iPhone SE", "iPhone XS Max"].identified(by: \.self)) { deviceName in
- LandmarkList()
- .previewDevice(PreviewDevice(rawValue: deviceName))
- .previewDisplayName(deviceName)
- }
+ LandmarkList()
+ .environmentObject(UserData())
}
}
#endif
diff --git a/3 Handling User Input/StartingPoint/Landmarks/Landmarks/Supporting Views/LandmarkRow.swift b/3 Handling User Input/StartingPoint/Landmarks/Landmarks/Supporting Views/LandmarkRow.swift
index e90259e..ebeb7e9 100644
--- a/3 Handling User Input/StartingPoint/Landmarks/Landmarks/Supporting Views/LandmarkRow.swift
+++ b/3 Handling User Input/StartingPoint/Landmarks/Landmarks/Supporting Views/LandmarkRow.swift
@@ -14,6 +14,12 @@ struct LandmarkRow: View {
HStack {
landmark.image(forSize: 50)
Text(landmark.name)
+ Spacer()
+ if landmark.isFavorite {
+ Image(systemName: "star.fill")
+ .imageScale(.large)
+ .foregroundColor(.yellow)
+ }
}
}
}
diff --git a/3 Handling User Input/StartingPoint/Landmarks/Landmarks/UserData.swift b/3 Handling User Input/StartingPoint/Landmarks/Landmarks/UserData.swift
new file mode 100644
index 0000000..9f4615e
--- /dev/null
+++ b/3 Handling User Input/StartingPoint/Landmarks/Landmarks/UserData.swift
@@ -0,0 +1,16 @@
+
+import Combine
+import SwiftUI
+
+final class UserData: BindableObject {
+
+ let didChange = PassthroughSubject()
+
+ var showFavoritesOnly = false {
+ didSet { didChange.send(self) }
+ }
+
+ var landmarks = landmarkData {
+ didSet { didChange.send(self) }
+ }
+}