[ Swift UI 강좌 ] 3. 스위프트 iOS - @State 속성 @Binding 속성

스위프트 UI 에서 @State와 @Binding 이라는 어노테이션이 있습니다. 아직 정확히 이해한 것은 아니지만 Rx의 바인딩과 비슷한 것 같습니다. 일단 화면을 구성해서 어떻게 사용하는지를 정리하고 나중에 해당 속성에 대해서 따로 포스팅 하겠습니다. 이번 프로젝트 예제는 iOS 앱을 보고 macOS 에서도 구현이 가능할 수도 있겠다고 생각해서 해봤는데 역시 잘 됩니다. 스위프트 UI 좋네요. 아무튼 정리하는 차원에서 간단한 예제를 만들어 보겠습니다.

 

▼ 1. 프로젝트를 생성합니다. State And Binding 이라고 선택해서 만듭니다. iPhone 앱이든 mac 앱이든 상관 없습니다. 저는 mac 용앱으로 만들겠습니다.

1. Swift UI 프로젝트 생성


 

▼ 2. mood 라는 enum 값을 생성합니다. happy, sad, upsidedown, cat 이렇게 4가지의 String 타입의 enum 값입니다. 조금 뒤에 선택 Picker에서 값으로 사용됩니다.

enum Mood: String {
    case happy = "😀"
    case sad = "☹️"
    case upsidedown = "🙃"
    case cat = "🐱"
}

2. enum 값 생성


▼ 3. 상단에 3가지 속성을 추가합니다. 그리고 기존의 텍스트를 지우고 HStack으로 감싼 새로운 컨트롤을 하나 만듭니다. 텍스트필드, Color 픽커, 그리고 위에서 만든 enum 값을 선택하는 픽커를 묶어줍니다.

@State var name: String = "Hello"
@State var favoriteColor: Color = .red
@State var mood: Mood = Mood.happy
HStack {
    TextField("Name", text: $name)
    ColorPicker("Favorite Color", selection: $favoriteColor)
    Picker("Mood", selection: $mood) {
        Text(Mood.happy.rawValue).tag(Mood.happy)
        Text(Mood.happy.rawValue).tag(Mood.happy)
        Text(Mood.happy.rawValue).tag(Mood.happy)
        Text(Mood.happy.rawValue).tag(Mood.happy)
    }
    .pickerStyle(SegmentedPickerStyle())
}.padding()

3. 선택 컨트롤 생성


 

▼ 4. 새로 만든 컨트롤 바로 아래에 결과값을 표시하기 위한 VStack으로 아이콘을 만들어줍니다.

VStack {
    VStack {
        Text(mood.rawValue)
        Text(name)
            .foregroundColor(.white)
    }
    .font(.largeTitle)
    .padding()
    .background(favoriteColor)
    .cornerRadius(12)
}.padding()

3. 아이콘 생성


 

▼ 5. 이제 화면은 모두 만들었으나 정리를 위해서 따로 View로 분리해서 만들어보겠습니다.

struct StatusIcon: View {
    let name: String
    let favoriteColor: Color
    let mood: Mood
    
    var body: some View {
        VStack {
            VStack {
                Text(mood.rawValue)
                Text(name)
                    .foregroundColor(.white)
            }
            .font(.largeTitle)
            .padding()
            .background(favoriteColor)
            .cornerRadius(12)
        }.padding()
    }
}

5. 아이콘 분리


 

▼ 6. 처음에 만들었던 컨트롤도 따로 분리해서 만들어줍니다. 동적으로 값을 받기 위해서 Binding 어노테이션을 추가해줍니다.

struct StatusControl: View {
    @Binding var name: String
    @Binding var favoriteColor: Color
    @Binding var mood: Mood
    var body: some View {
    HStack {
        TextField("Name", text: $name)
        ColorPicker("Favorite Color", selection: $favoriteColor)
        Picker("Mood", selection: $mood) {
            Text(Mood.happy.rawValue).tag(Mood.happy)
            Text(Mood.happy.rawValue).tag(Mood.happy)
            Text(Mood.happy.rawValue).tag(Mood.happy)
            Text(Mood.happy.rawValue).tag(Mood.happy)
        }
        .pickerStyle(SegmentedPickerStyle())
    }.padding()
    }
}

6. 컨트롤 분리


 

▼ 7. 이제 상단에 VStack을 만들어 조금 전에 만든 2개의 뷰를 생성합니다. 주의하실 점은 첫번째 컨트롤에는 $ 표시를 포함한 값을 인자로 줍니다. Binding 값과 연결하기 위해서입니다.

struct ContentView: View {
    @State var name: String = "Hello"
    @State var favoriteColor: Color = .red
    @State var mood: Mood = Mood.happy
    var body: some View {
        VStack {
            StatusControl(name: $name, favoriteColor: $favoriteColor, mood: $mood)
            StatusIcon(name: name, favoriteColor: favoriteColor, mood: mood)
        }
    }
}

7. 분리된 뷰 객체 생성


 

▼ 8. 이제 앱을 실행해보면 화면이 잘 나옵니다. 텍스트 필드를 수정하거나 색상을 변경하거나 아이콘을 선택하면 화면이 동적으로 바뀝니다.

8. 앱 실행


 

▼ 9. 전체 코드입니다.

import SwiftUI

enum Mood: String {
    case happy = "😀"
    case sad = "☹️"
    case upsidedown = "🙃"
    case cat = "🐱"
}

struct ContentView: View {
    @State var name: String = "Hello"
    @State var favoriteColor: Color = .red
    @State var mood: Mood = Mood.happy
    var body: some View {
        VStack {
            StatusControl(name: $name, favoriteColor: $favoriteColor, mood: $mood)
            StatusIcon(name: name, favoriteColor: favoriteColor, mood: mood)
        }
    }
}

struct StatusControl: View {
    @Binding var name: String
    @Binding var favoriteColor: Color
    @Binding var mood: Mood
    var body: some View {
    HStack {
        TextField("Name", text: $name)
        ColorPicker("Favorite Color", selection: $favoriteColor)
        Picker("Mood", selection: $mood) {
            Text(Mood.happy.rawValue).tag(Mood.happy)
            Text(Mood.happy.rawValue).tag(Mood.happy)
            Text(Mood.happy.rawValue).tag(Mood.happy)
            Text(Mood.happy.rawValue).tag(Mood.happy)
        }
        .pickerStyle(SegmentedPickerStyle())
    }.padding()
    }
}

struct StatusIcon: View {
    let name: String
    let favoriteColor: Color
    let mood: Mood
    
    var body: some View {
        VStack {
            VStack {
                Text(mood.rawValue)
                Text(name)
                    .foregroundColor(.white)
            }
            .font(.largeTitle)
            .padding()
            .background(favoriteColor)
            .cornerRadius(12)
        }.padding()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

 

지금까지 간단하게 State, Binding 어노테이션을 이용해서 값을 동적으로 할당해 주는 방법을 알아봤습니다. 아직 저도 자세히 공부한 것이 아니라서 정리후에 나중에 실제 문법도 공부해서 포스팅 하겠습니다.

 

tttap.tistory.com/106

 

[ Swift UI 강좌 ] 1. 스위프트 iOS - 버튼 이벤트 만들기

스위프트 UI 가 나온지 벌써 1년이 넘어갑니다. 계속 스위프트와 오토레이아웃으로 업무를 하다보니까 배울 시간이 없었는데요. 이제 조금씩 배워보려고합니다. 개인 정리차 오늘 부터 계속 스

tttap.tistory.com

tttap.tistory.com/116

 

[ Swift UI 강좌 ] 2. 스위프트 iOS - 네비게이션 이동하기

이번에는 스위프트 UI를 통해서 네비게이션 컨트롤러?는 아니고 네비게이션 뷰를 만들어보겠습니다. 저도 좀 생소하긴 한데요. 스위프트 UI는 별도로 컨트롤러가 없는 것 같습니다. 물론 더 공부

tttap.tistory.com

 

댓글

Designed by JB FACTORY