사용자가 개성을 나타낼 수 있도록 사용자 프로필을 만들어보자. 프로필을 변경할 수 있도록 편집 모드를 추가하고 기본 설정 화면을 디자인해보자. 데이터 입력을 위해 공통 사용자 인터페이스 컨트롤로 작업하고 사용자가 변경 사항을 저장할 때마다 랜드마크 모델 타입을 업데이트해야 한다.

Section 1. Display a User Profile

랜드마크 앱은 일부 구성 정보와 설정을 로컬로 저장한다. 이를 사용자가 세부 정보를 편집하기 전에 편집 컨트롤이 없는 ProfileSummary 뷰에 표시해보자.

스크린샷 2023-05-05 오후 2.19.39.png

toolbar(content:)

func toolbar<Content>(@ToolbarContentBuilder content: () -> Content) -> some View where Content : ToolbarContent

지정된 항목으로 툴바 또는 네비게이션 바를 채운다.

Section 2. Add an Edit Mode

사용자는 자신의 ProfileSummary 뷰와 ProfileEditor 뷰를 전환할 수 있어야 하므로 ProfileHostEditButton을 추가하고 개별 값을 수정할 수 있는 컨트롤이 있는 편집 뷰를 만들어보자.

스크린샷 2023-05-05 오후 2.20.18.png

Environment

@frozen @propertyWrapper struct Environment<Value>

뷰의 environment에서 값을 읽는 프로퍼티 래퍼

SwiftUI는 @Environment 프로퍼티 래퍼를 사용해 접근할 수 있는 값에 대한 Environment 저장소를 제공한다.

ProfileHost.swift

// summary view 와 edit mode 를 static하게 호스팅하는 뷰
struct ProfileHost: View {
    // SwiftUI는 @Environment 프로퍼티 래퍼를 사용해 접근할 수 있는 값에 대한 Environment 저장소를 제공한다.
    @Environment(\\.editMode) var editMode
    @EnvironmentObject var modelData: ModelData
    @State private var draftProfile = Profile.default
    
    var body: some View {
        VStack(alignment: .leading, spacing: 20) {
            HStack {
                Spacer()
                EditButton()
            }
            
            if editMode?.wrappedValue == .inactive /* enum EditMode */ {
                ProfileSummary(profile: modelData.profile)
            } else {
                Text("Profile Editor")
            }
        }
        .padding()
    }
}

struct ProfileHost_Previews: PreviewProvider {
    static var previews: some View {
        ProfileHost()
            .environmentObject(ModelData())
        // 이 뷰는 @EnvironmentObject 속성을 사용하지 않지만 하위 뷰가 해당 속성을 사용하므로 상위 뷰에서도 전달해줘야 오류가 발생하지 않음
    }
}

Section 3. Define the Profile Editor

ProfileEditor 뷰는 주로 프로필의 개별 세부 정보를 변경하는 다양한 컨트롤로 구성되며, 일부 변경할 수 없는 항목은 뷰에 표시하지 않는다. ProfileSummary 뷰와의 일관성을 위해 편집 뷰에서도 동일한 순서로 프로필 세부 정보를 추가해보자.

스크린샷 2023-05-05 오후 2.20.35.png