



var body: some View {
NavigationView{
//passing the model data's landmark array to the List initializer
List{
// use $prefix to access a state variable
Toggle(isOn: $showFavoritesOnly){
Text("Favorites only")
}
ForEach(filteredLandmarks) {
landmark in
NavigationLink(destination: LandmarkDetail(landmark: landmark)) {
LandmarkRow(landmark: landmark)
}
}
}
//set the title of the navigation bar when displaying the list.
.navigationTitle("Landmarks")
}
user가 특정 landmark의 favorite을 control하게 하기 위해서는, landmark data를 observable object로 store해야한다.
observable object란 네 data를 위한 custom object이다. 이 data는 swiftui에 의해 감독되어 수정된다.(update, refresh)
1. ModelData.swift에서 Combine을 import하고, Modeldata class를 만든다.
2. landmarks변수를 class안에 넣고, @Published를 추가한다.
import Combine
final class ModelData: ObservableObject{
//Create an array of landmarks that you initialize from landmarkData.json
@Published var landmarks: [Landmark] = load("landmarkData.json")
}
struct LandmarkList: View {
@EnvironmentObject var modelData: ModelData
@State private var showFavoritesOnly = false
/// ture => 별표 된것만 보여줌.
/// false => 다 보여줌.
var filteredLandmarks: [Landmark] {
modelData.landmarks.filter {
landmark in (!showFavoritesOnly || landmark.isFavorite)
}
}
struct LandmarkList_Previews: PreviewProvider {
static var previews: some View {
LandmarkList()
.environmentObject(ModelData())
}
}
struct LandmarkDetail_Previews: PreviewProvider {
static var previews: some View {
LandmarkDetail(landmark: ModelData().landmarks[0])
}
}
struct LandmarkRow_Previews: PreviewProvider {
static var landmarks = ModelData().landmarks
static var previews: some View {
Group{
LandmarkRow(landmark: landmarks[0])
LandmarkRow(landmark: landmarks[1])
} // set a size that approximates a row in a list
.previewLayout(.fixed(width: 300, height: 70))
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.environmentObject(ModelData())
}
}
import SwiftUI
@main //attribute identifies the app's entry point
struct LantmarksApp: App {
@StateObject private var modelData = ModelData()
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(modelData)
}
}
}
detail에서 별표를 클릭 할 수 있도록 바꿈.
1. FavoriteButton.swift를 새로 만듦.
2. isSet binding을 추가함.
얘는, button의 current state를 알려줌.
3. preview에 constant value를 제공함.
4. body에 toggle button을 추가하고, button의 appearance를 state에 따라 변하게함.
import SwiftUI
struct FavoriteButton: View {
@Binding var isSet : Bool
var body: some View {
Button(action: {
isSet.toggle()
}) {//isSet이 true면 노란, 꽉찬 별
Image(systemName: isSet ? "star.fill" : "star")
.foregroundColor(isSet ? Color.yellow: Color.gray)
}
}
}
struct FavoriteButton_Previews: PreviewProvider {
static var previews: some View {
FavoriteButton(isSet: .constant(true))
}
}
폴더 구조 수정. 
LandmarkDetail.swift에서,
@EnvironmentObject var modelData: ModelData
var landmark: Landmark
var landmarkIndex: Int {
modelData.landmarks.firstIndex(where: {
$0.id == landmark.id
})!
}
var body: some View{
느낌표 안 붙였더니 에러떴는데 왜일까....흑...ㅠㅠ
VStack(alignment: .leading) {
HStack {
Text(landmark.name)
.font(.title)
.fontWeight(.bold)
.foregroundColor(Color.black)
.padding(.all, 3.0)
FavoriteButton(isSet: $modelData.landmarks[landmarkIndex].isFavorite)
}