1-3. Handling User Input

dumdum·2021년 4월 23일

SwiftUI

목록 보기
3/7

Mark the User's Favorite Landmarks.

  1. Landmark.swfit에 isFavorite변수 추가. (josn에 있는 변수임)
  2. LandmarkROw.swift에서 if문으로, landmark.isFavorite가 true면 Image를 반환하도록 설정함. modifier로 색깔 yellow로 바꿔줌.

Filter the List View

  1. LandmarkLsit.swift에서, add a state property
  2. filteredLandmarks변수 추가하고, filter method로 show가 true일 때, isfavorite가 true인 값만 filteredLandmarks에 저장 한 후, body의 list view 변수를 filteredLandmarks로 바꿔줌.
    apple, filter, { } 안이 참인것만 return해서 변수에 넣어줌.

Add a Control to Toggle the State

  1. ForEach group으로 landmarks를 rows로 바꿈.
    static and dynamic view를 list로 combine하거나
    2개 이상의 다른 dynamic view그룹을 combine할 때 ForEach를 사용함.
  2. Toggle을 통해 show값을 바꿔줌.
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")
        }

Use an Observable Object for Storage

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")
}

Adopt the Model Object in your Views

  1. LandmarkList.swift에서 @EnvironmentObject property를 추가한다.
  2. landmark.filter를 modelData에 대해 한다.
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)
        }
    }
  1. LandmarkList, LandmarkDetail, LandmarkRow, ContentView preview에서 environmentObject modifier를 추가하여 ModelData object를 통해 work 하도록 설정한다.
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())
    }
}
  1. LandmarksApp이 model instance를 생성하도록 update하고, 이것을 environmentObject modifier를 사용해서 ContentView에 supply.
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)
        }
    }
}

Create a Favorite Button for Each Landmark

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))
    }
}
  1. 폴더 구조 수정.

  2. LandmarkDetail.swift에서,

  • compute the index of the input landmark by comparing it with the model data...
    라는데 뭐라는지 모르겠음.

    @EnvironmentObject var modelData: ModelData
    var landmark: Landmark
    var landmarkIndex: Int {
        modelData.landmarks.firstIndex(where: {
            $0.id == landmark.id
        })!
    }
    
    var body: some View{

느낌표 안 붙였더니 에러떴는데 왜일까....흑...ㅠㅠ

  1. body의 Vstack의 text를 Hstack으로 묶고 FavoriteButton을 추가함.
    VStack(alignment: .leading) {
                HStack {
                    Text(landmark.name)
                        .font(.title)
                        .fontWeight(.bold)
                        .foregroundColor(Color.black)
                        .padding(.all, 3.0)
                    FavoriteButton(isSet: $modelData.landmarks[landmarkIndex].isFavorite)
                }

index어쩌구부터 저언혀 못알아듣겠다!

profile
Noteing WIll

0개의 댓글