ボタンのタップや表示のフィルター
チュートリアルより。 まず、セルにスターの表示非表示をつける。
struct LandmarkRow: View { var landmark: Landmark var body: some View { HStack { landmark.image .resizable() .frame(width: 50, height: 50) Text(landmark.name) Spacer() if landmark.isFavorite { Image(systemName: "star.fill") .imageScale(.medium) .foregroundColor(.yellow) } } } }
これはif文で簡単につけられる。
次にリストでお気に入りだけを表示するようにトグルをつける。
struct LandmarkList: View { @EnvironmentObject private var userData: UserData var body: some View { NavigationView { List { Toggle(isOn: $userData.showFavoritesOnly) { Text("Show Favorites Only") } ForEach(userData.landmarks) { landmark in if !self.userData.showFavoritesOnly || landmark.isFavorite { NavigationLink( destination: LandmarkDetail(landmark: landmark) .environmentObject(self.userData) ) { LandmarkRow(landmark: landmark) } } } } .navigationBarTitle(Text("Landmarks")) } } }
@EnvironmentObjectに指定しているUserDataはその属性を変化させると表示が更新される。 $userData.showFavoritesOnlyはToggle(isOn:)にバインドさせている。
詳細画面ではスターを付けられるようにしている。
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 { MapView(coordinate: landmark.locationCoordinate) .edgesIgnoringSafeArea(.top) .frame(height: 300) CircleImage(image: landmark.image) .offset(x: 0, y: -130) .padding(.bottom, -130) VStack(alignment: .leading) { 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(Color.yellow) } else { Image(systemName: "star") .foregroundColor(Color.gray) } } } HStack(alignment: .top) { Text(landmark.park) .font(.subheadline) Spacer() Text(landmark.state) .font(.subheadline) } } .padding() Spacer() } } } struct LandmarkDetail_Previews: PreviewProvider { static var previews: some View { let userData = UserData() return LandmarkDetail(landmark: userData.landmarks[0]) .environmentObject(userData) } }
最後にUserDataは
import Combine import SwiftUI final class UserData: ObservableObject { @Published var showFavoritesOnly = false @Published var landmarks = landmarkData }
であって、@PublishedをつけたObservableObjectであることがポイント。