Project Jo

Data Flow Through SwiftUI 본문

Developer/Swift UI

Data Flow Through SwiftUI

Project Jo 2020. 8. 20. 19:30

WWDC 강의를 참고하여 데이터 흐름에 관하여 정리를 하려 한다.

https://developer.apple.com/videos/play/wwdc2019/226

 

Data Flow Through SwiftUI - WWDC 2019 - Videos - Apple Developer

SwiftUI was built from the ground up to let you write beautiful and correct user interfaces free of inconsistencies. Learn how to connect...

developer.apple.com

 

강의에서 중요한건 @Binding @State @Environment, BindableObject, Property 이다.

부족하지만 내가 이해한 각각의 키워드를 이곳에 정리 하고자 한다.

 

 

@State

가장 기본이 되는 키워드로 SwiftUI 에 표시되는 화면과 내부 변수의 다리 역활을 하며, 변수의 값이 변경되면 UI 가 갱신 된다.

struct ContentView: View {
    @State var isShow: Bool = true
    
    var body: some View {
        VStack {
            Button(action: buttonTouch) {
                Text("버튼")
            }
            
            if isShow {
                Text("Hello, World!")
            }
        }
    }
    
    func buttonTouch() {
        isShow = !isShow
    }
}

예제 소스를 보면 isShow 변수 앞에 @State 를 사용하였다.

해당 값이 변경 된다면 Text 인 Hello, World! 가 보이거나 보이지 않게 변경된다.

 

 

@Binding

Slider 나 Toggle 의 경우 값이 실시간으로 변경되는데, 이 변경을 바로 변수에 적용해주도록 앞에 $를 붙여 넣어준다.

이렇게 되면 변수에 바로 적용이 되고, 해당 변수에 @State 를 사용하여 바로 화면에 적용도 가능하다.

struct ContentView: View {
    @State var opacity: Double = 1
    
    var body: some View {
        VStack {
            Text("Hello, World!")
                .opacity(opacity)
            
            Slider(value: $opacity, in: 0...1, step: 0.1)
                .padding(.horizontal)
        }
    }
}

예제 소스를 보면 Slider 의 값이 변할때 opacity 변수로 바로 저장이 되고 Text 의 투명값이 실시간으로 변경된다.

 

 

BindableObject (ObservableObject)

BindableObject 이름이 ObservableObject 로 변경되었다.

 

@State 는 외부에서 접근이 안되는 내부 뷰 메모리에 보관되는 privete 한 변수이다.

 

외부에서 접근을 해야하는 경우 ObservableObject 를 상속하는 클래스를 만들어야 한다.

UI 에 바로 반영되는 변수에 @Published 키워드를 설정하면 해당 변수의 값이 변경되는 경우 바로 반영이 된다.

 

특정 상황에서 화면 변경이 필요한 경우 값에 didSet 을 이용해 objectWillChange.send() 함수를 이용하거나, 특정 조건에서 objectWillChange.send() 함수를 호출하도록 한다.

 

@ObservedObject 키워드를 사용하여 클래스를 생성하고, 값을 사용하면 된다.

class MyOpacity: ObservableObject
{
    @Published var opacity: Double {
        didSet {
            objectWillChange.send()
        }
    }
    
    init(opacity: Double = 1)
    {
        self.opacity = opacity
    }
}

struct ContentView: View {
    @ObservedObject var myOpacity: MyOpacity = MyOpacity()
    
    var body: some View {
        VStack {
            VStack {
                Text("Hello, World!")
                    .opacity(myOpacity.opacity)
                
                Slider(value: $myOpacity.opacity, in: 0...1, step: 0.1)
                    .padding(.horizontal)
            }
        }
    }
}

예제 소스를 보면 MyOpacity 클래스는 ObservableObject 를 상속하였다.

@Published 키워드로 opacity 를 개시 하였고, 해당 값이 변경될때 didSet 을 통해서 objectWillChange.send() 함수 호출까지 진행하였다.

(objectWillChange.send() 를 제거 하더라도 @Published 키워드가 설정되어 있기에 자동으로 화면이 갱신 된다.)

 

 

@EnvironmentObject

Environment 를 직역하자면 환경이기에 해당 키워드는 환경 객체 이다.

하위에 속해있는 모든 화면(View) 에서 공통으로 사용되게 설정이 가능하다.

class MyOpacity: ObservableObject
{
    @Published var opacity: Double {
        didSet {
            objectWillChange.send()
        }
    }
    
    init(opacity: Double = 1)
    {
        self.opacity = opacity
    }
}

struct ContentView: View {
    
    var body: some View {
        VStack {
            ChildTextView()
            ChildSliderView()
        }
    }
}

struct ChildTextView: View {
    @EnvironmentObject var myOpacity: MyOpacity
    
    var body: some View {
        Text("Hello, World!")
            .opacity(myOpacity.opacity)
    }
}

struct ChildSliderView: View {
    @EnvironmentObject var myOpacity: MyOpacity
    
    var body: some View {
        Slider(value: $myOpacity.opacity, in: 0...1, step: 0.1)
            .padding(.horizontal)
    }
}

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

이번 예제 소스는 길게 되었는데, 뷰를 나누다 보니 길어 졌을 뿐 복잡하지 않다.

 

ContentView_Previews 는 SwiftUI 를 구성하는 미리보기 객제인데 이곳의 생성자에 .environmentObject(MyOpacity()) 를 추가하였다.

환경 객체로 MyOpacity 클래스를 설정한 것이다.

 

하위 뷰인 ChildTextView 와 ChildSliderView 에서 @EnvironmentObject 키워드를 사용하여 환경 객체를 사용하도록 선언하였고, 이전 예제와 마찬가지로 사용하였다.

 

이전 예제와 마찬가지로 슬라이드를 이동시 투명값이 변경되는것을 확인 할 수 있다.

(여기서 궁굼한건 EnvironmentObject 는 자동으로 ObservedObject 가 설정 되는건가...?)

'Developer > Swift UI' 카테고리의 다른 글

Swift UI 기초  (0) 2020.07.27
Swift UI : Building Your First App  (0) 2020.07.27