πŸ’» 개발/iOS

[iOS / SwiftUI] λ‹€μ–‘ν•œ μƒνƒœ ν”„λ‘œνΌν‹°λ“€μ„ μ•Œμ•„λ³΄μž!

2022. 10. 24. 13:52
λͺ©μ°¨
  1. State와 Binding
  2. Observable 객체
  3. Environment 객체
  4. 정리
  5. πŸ‘€ 회고

State와 Binding

μ§€λ‚œ μ‹œκ°„ @State와 @Binding ν”„λ‘œνΌν‹° λž˜νΌμ— λŒ€ν•΄ ν•™μŠ΅ν–ˆλ‹€.

 

1. @State

@State ν”„λ‘œνΌν‹° 래퍼λ₯Ό μ‚¬μš©ν•΄μ„œ μƒνƒœ ν”„λ‘œνΌν‹°λ₯Ό μž‘μ„±ν•˜λ©΄ ν•΄λ‹Ή ν”„λ‘œνΌν‹°κ°€ μ„ μ–Έλœ 뷰와 바인딩할 수 있게 λœλ‹€.

 

μ’€ 더 μ‰½κ²Œ μ„€λͺ…ν•˜μžλ©΄ 뷰와 바인딩이 λ˜μ–΄ μžˆλŠ” μƒνƒœν”„λ‘œνΌν‹°μ— 변경이 μΌμ–΄λ‚˜λ©΄ μžλ™μœΌλ‘œ λ·°κ°€ κ°±μ‹ λœλ‹€λŠ” 말이닀.

μ½”λ“œλ‘œ 직접 μ‚΄νŽ΄λ³΄μž.

 

μ•„λž˜ μ½”λ“œλŠ” λ²„νŠΌμ„ ν΄λ¦­ν•˜λ©΄ μˆ«μžκ°€ 1μ”© μ¦κ°€ν•˜λ„λ‘ κ΅¬ν˜„ν•œ 앱이닀.

struct ContentView: View {
    @State private var number: Int = 0
    
    var body: some View {
        VStack {
            Text("\(self.number)")
            
            Button(action: {
                self.number += 1
            }) {
                Text("λˆŒλŸ¬μ£Όμ„Έμš”!")
            }
        }
    }
}

앱을 μ‹€ν–‰μ‹œν‚€κ³  λ²„νŠΌμ„ 눌러보면 λˆ„λ₯Ό λ•Œλ§ˆλ‹€ μˆ«μžκ°€ 1μ”© μ¦κ°€ν•˜λŠ” 것을 λ³Ό 수 μžˆλ‹€.

μˆ«μžκ°€ μ¦κ°€ν•œ λ’€ 이λ₯Ό μ°Έμ‘°ν•˜κ³  μžˆλŠ” λ·°λ₯Ό κ°±μ‹ ν•˜μ§€ μ•Šμ•„λ„ μ•Œμ•„μ„œ κ°±μ‹ λœλ‹€.

 

κ·Έλ ‡λ‹€λ©΄ @BindingλŠ” λ¬΄μ—‡μΌκΉŒ?

 

2. @Binding

μœ„μ—μ„œ μž‘μ„±ν•œ μ½”λ“œλŠ” μƒνƒœ ν”„λ‘œνΌν‹°λ₯Ό μ„ μ–Έν•œ λ·°μ—μ„œ μƒνƒœ ν”„λ‘œνΌν‹°λ₯Ό 직접 μ‚¬μš©ν•˜κ³  μžˆλ‹€.

즉, μ„ μ–Έκ³Ό μ‚¬μš©μ΄ ν•˜λ‚˜μ˜ λ·°(Struct)μ—μ„œ μ§„ν–‰λœλ‹€λŠ” 말이닀.

 

κ·Έλ ‡λ‹€λ©΄ 메인 λ·°(λΆ€λͺ¨)μ—μ„œ μ„ μ–Έν•œ μƒνƒœ ν”„λ‘œνΌν‹°λ₯Ό μ„œλΈŒ λ·°(μžμ‹)μ—μ„œ μ‚¬μš©ν•œλ‹€λ©΄ μ–΄λ–»κ²Œ 될까?

struct ContentView: View {
    @State private var number: Int = 0
    
    var body: some View {
        VStack {
            Text("\(self.number)")
            
            Button(action: {
                self.number += 1
            }) {
                Text("λˆŒλŸ¬μ£Όμ„Έμš”!")
            }
        }
    }
}

struct SubView: View {
    var body: some View {
        VStack {
            Text("This is SubView")
            Text("\(self.number)")
        }
        .padding()
        .background(.gray)
    }
}

μ½”λ“œλ₯Ό μž‘μ„±ν•˜κ³  λΉŒλ“œλ₯Ό μ§„ν–‰ν•˜λ©΄ 컴파일 μ—λŸ¬κ°€ λ°œμƒν•œλ‹€.

 

SubView 내뢀에 number ν”„λ‘œνΌν‹°κ°€ μ„ μ–Έλ˜μ–΄ μžˆμ§€ μ•ŠκΈ° λ•Œλ¬Έμ΄λ‹€.

 

κ·Έλ ‡λ‹€λ©΄ SubView 내뢀에 number ν”„λ‘œνΌν‹°λ₯Ό μ„ μ–Έν•˜λ©΄ μ–΄λ–»κ²Œ 될까?

struct ContentView: View {
    @State private var number: Int = 0
    
    var body: some View {
        VStack {
            Text("\(self.number)")
            
            Button(action: {
                self.number += 1
            }) {
                Text("λˆŒλŸ¬μ£Όμ„Έμš”!")
            }
        }
    }
}

struct SubView: View {
	private var number: Int = 0
    
    var body: some View {
        VStack {
            Text("This is SubView")
            Text("\(self.number)")
        }
        .padding()
        .background(.gray)
    }
}

μ΄λ²ˆμ—” λΉŒλ“œλŠ” μ •μƒμ μœΌλ‘œ μ§„ν–‰λœλ‹€.

 

ν•˜μ§€λ§Œ λ²„νŠΌμ„ 클릭해도 μ„œλΈŒλ·°μ— μžˆλŠ” ν…μŠ€νŠΈλŠ” λ³€κ²½λ˜μ§€ μ•ŠλŠ”λ‹€.

SubView의 number와 ContentView의 numberλŠ” μ„œλ‘œ λ‹€λ₯Έ ν”„λ‘œνΌν‹°μ΄κΈ° λ•Œλ¬Έμ΄λ‹€.

 

κ·Έλ ‡λ‹€λ©΄ 두 개λ₯Ό μ—°κ²°ν•΄μ£Όλ©΄ 문제λ₯Ό ν•΄κ²°ν•΄ 쀄 수 μžˆμ§€ μ•Šμ„κΉŒ?

struct ContentView: View {
    @State private var number: Int = 0
    
    var body: some View {
        VStack {
            Text("\(self.number)")
            
            Button(action: {
                self.number += 1
            }) {
                Text("λˆŒλŸ¬μ£Όμ„Έμš”!")
            }
            
            SubView(number: number)
        }
    }
}

struct SubView: View {
	// μƒμ„±μžλ₯Ό 톡해 number 전달
    init(number: Int) {
        self.number = number
    }
    
    private var number: Int = 0
    
    var body: some View {
        VStack {
            Text("This is SubView")
            Text("\(self.number)")
        }
        .padding()
        .background(.gray)
    }
}

μƒμ„±μžλ₯Ό ν†΅ν•΄μ„œ 메인 뷰의 numberλ₯Ό μ „λ‹¬ν–ˆλ”λ‹ˆ μ„œλΈŒ λ·°μ—μ„œλ„ 화면이 κ°±μ‹ λ˜λŠ” 것을 λ³Ό 수 μžˆλ‹€.

 

μ„œλ‘ μ΄ κΈΈμ—ˆμ§€λ§Œ @Binding ν”„λ‘œνΌν‹° 래퍼λ₯Ό ν†΅ν•΄μ„œ κ°„λ‹¨ν•œ ν˜•νƒœλ‘œ μž‘μ„±ν•  수 μžˆλ‹€.

struct ContentView: View {
    @State private var number: Int = 0
    
    var body: some View {
        VStack {
            Text("\(self.number)")
            
            Button(action: {
                self.number += 1
            }) {
                Text("λˆŒλŸ¬μ£Όμ„Έμš”!")
            }
            
            SubView(number: $number)
        }
    }
}

struct SubView: View {
    @Binding var number: Int
    
    var body: some View {
        VStack {
            Text("This is SubView")
            Text("\(self.number)")
        }
        .padding()
        .background(.gray)
    }
}

μƒμ„±μžλ₯Ό ν†΅ν•΄μ„œ ν”„λ‘œνΌν‹°λ₯Ό μ „λ‹¬ν•œ 방식과 μœ μ‚¬ν•˜λ‹€.

차이점은 μ„œλΈŒ λ·°μ—μ„œ @Binding ν”„λ‘œνΌν‹° 래퍼둜 λ³€μˆ˜λ₯Ό μ„ μ–Έλ§Œ ν•œλ‹€λŠ” 것이닀.

 

메인 λ·°μ—μ„œλŠ” Argument둜 $numberλ₯Ό μ „λ‹¬ν•œλ‹€.

μ—¬κΈ°μ„œ λͺ…심해야할 것은 $(λ‹¬λŸ¬)!

 

$(λ‹¬λŸ¬)기호λ₯Ό 빼먹으면 컴파일 μ—λŸ¬κ°€ λ°œμƒν•œλ‹€.

 

μ„œλΈŒ λ·°μ—μ„œ Binding<Int> ν˜•μœΌλ‘œ numberλ₯Ό μ„ μ–Έν–ˆλŠ”λ° Intν˜• numberλ₯Ό μ „λ‹¬ν•΄μ„œ λ°œμƒν•˜λŠ” νƒ€μž… μ—λŸ¬μ΄λ‹€.

 

처음 μ˜λ„ν–ˆλ˜ λŒ€λ‘œ μ •μƒμ μœΌλ‘œ μž‘λ™ν•˜λŠ” 것을 λ³Ό 수 μžˆλ‹€.

 

ν•˜μ§€λ§Œ 의문점이 ν•œ κ°€μ§€κ°€ μžˆλ‹€.  πŸ§
μƒμ„±μžλ₯Ό ν†΅ν•΄μ„œ μ „λ‹¬ν•˜λŠ” 방식도 μžˆλŠ”λ° ꡳ이 @Bindingμ΄λΌλŠ” ν”„λ‘œνΌν‹° λž˜νΌκ°€ λ“±μž₯ν•œ μ΄μœ λŠ” λ¬΄μ—‡μΌκΉŒ?

 

μ§€κΈˆ μ˜ˆμ‹œλ“€μ€ λ·° μ‚¬μ΄μ—μ„œ 단방ν–₯으둜 데이터λ₯Ό μ£Όκ³  λ°›κ³  μžˆλ‹€.

메인 λ·°(ContentView) -> μ„œλΈŒ λ·°(SubView) λ°©ν–₯으둜, λ‹€μ‹œ 말해 μ„œλΈŒ 뷰에 νŒŒλΌλ―Έν„°λ‘œ 메인 뷰의 ν”„λ‘œνΌν‹°λ₯Ό μ „λ‹¬ν•˜κ³  μžˆλ‹€.

 

μ–‘λ°©ν–₯으둜 데이터λ₯Ό μ£Όκ³  받도둝 μ½”λ“œλ₯Ό 변경해보면 @Binding을 μ‚¬μš©ν•˜λ €λŠ” μ΄μœ μ— λŒ€ν•΄ λͺ…ν™•ν•˜κ²Œ μ•Œ 수 μžˆλ‹€.

struct ContentView: View {
    @State private var number: Int = 0
    
    var body: some View {
        VStack {
            Text("\(self.number)")
            
            Button(action: {
                self.number += 1
            }) {
                Text("λˆŒλŸ¬μ£Όμ„Έμš”!")
            }
            
            SubView(number: self.number)
        }
    }
}

struct SubView: View {
    private var number: Int = 0
    
    init(number: Int) {
        self.number = number
    }
    
    var body: some View {
        VStack {
            Text("This is SubView")
            Text("\(self.number)")
            
            Button(action: {
            	self.number += 1
            }) {
                Text("λˆŒλŸ¬μ£Όμ„Έμš”!")
            }
        }
        .padding()
        .background(.gray)
    }
}

μ„œλΈŒ 뷰에도 λ²„νŠΌμ„ λ‹¬μ•„μ„œ SubView 값도 λ³€κ²½ν•  수 μžˆλ„λ‘ μ½”λ“œλ₯Ό 변경해쀬닀.

 

ν•˜μ§€λ§Œ 컴파일 였λ₯˜λ₯Ό λ°œμƒμ‹œν‚¨λ‹€.

View μžμ²΄κ°€ Structμ΄λ―€λ‘œ Immutableν•˜κΈ° λ•Œλ¬Έμ΄λ‹€.

 

컴파일 μžμ²΄κ°€ μ•ˆλ˜μ§€λ§Œ λ…Όλ¦¬μ μœΌλ‘œ 생각해보면 μš°λ¦¬κ°€ κ΅¬ν˜„ν•˜λ €λŠ” κΈ°λŠ₯은 일반적인 ν”„λ‘œνΌν‹°λ‘œλŠ” λΆˆκ°€λŠ₯ν•˜λ‹€λŠ” 것을 μ•Œ 수 μžˆλ‹€.

메인 λ·° 내뢀에 μ„œλΈŒ λ·° μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜κ³  νŒŒλΌλ―Έν„°λ‘œ ν”„λ‘œνΌν‹° 값을 μ „λ‹¬ν•˜κ³  μžˆλ‹€.

메인 λ·°μ—μ„œλ„ μ„œλΈŒ 뷰의 ν”„λ‘œνΌν‹°λ₯Ό μ ‘κ·Όν•˜κΈ° μœ„ν•΄μ„ , μ„œλΈŒ λ·° 내뢀에 메인 λ·° μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜μ—¬ νŒŒλΌλ―Έν„°λ‘œ μ „λ‹¬ν•˜κΈ° λ•Œλ¬Έμ΄λ‹€.

 

κ·Έλ ‡λ‹€λ©΄ 이 κΈ°λŠ₯은 κ΅¬ν˜„ν•  수 μ—†λŠ” κ²ƒμΌκΉŒ?

 

이 λ•Œ, @Binding ν”„λ‘œνΌν‹° 래퍼λ₯Ό μ‚¬μš©ν•˜λ©΄ λœλ‹€!

struct ContentView: View {
    @State private var number: Int = 0
    
    var body: some View {
        VStack {
            Text("\(self.number)")
            
            Button(action: {
                self.number += 1
            }) {
                Text("λˆŒλŸ¬μ£Όμ„Έμš”!")
            }
            
            SubView(number: $number)
        }
    }
}

struct SubView: View {
    @Binding var number: Int
    
    var body: some View {
        VStack {
            Text("This is SubView")
            Text("\(self.number)")
            
            Button(action: {
                self.number += 1
            }) {
                Text("λˆŒλŸ¬μ£Όμ„Έμš”!")
            }
        }
        .padding()
        .background(.gray)
    }
    
    mutating func addNumber() {
        self.number += 1
    }
}

μ •μƒμ μœΌλ‘œ 컴파일이 μ •μƒμ μœΌλ‘œ μ§„ν–‰λ˜κ³  앱을 싀행해보면 메인 뷰의 number와 μ„œλΈŒ 뷰의 numberκ°€ 같은 값을 κ°€μ§€κ³  있고, μ–‘λ°©ν–₯으둜 데이터λ₯Ό μ£Όκ³  λ°›κ³  μžˆλŠ” 것을 λ³Ό 수 μžˆλ‹€!

 

이것이 λ°”λ‘œ @Binding을 μ‚¬μš©ν•˜λŠ” μ΄μœ μ΄λ‹€.

 

ν•˜μ§€λ§Œ @Binding μ—­μ‹œ 단점은 μ‘΄μž¬ν•œλ‹€.

μ•žμ„œ λ§ν–ˆλ˜ κ²ƒμ²˜λŸΌ μƒνƒœ ν”„λ‘œνΌν‹°λŠ” ν”„λ‘œνΌν‹°λ₯Ό μ„ μ–Έν•œ λ·°μ—μ„œλ§Œ 접근이 κ°€λŠ₯ν•˜λ‹€.

ν•˜μœ„ λ·°κ°€ μ•„λ‹ˆκ±°λ‚˜ 바인딩이 κ΅¬ν˜„λ˜μ–΄ μžˆμ§€ μ•ŠμœΌλ©΄ λ‹€λ₯Έ λ·°μ—μ„œ 접근이 λΆˆκ°€λŠ₯ν•˜λ‹€.

λ˜ν•œ λ·° μžμ²΄μ— 쒅속적인 κ°œλ…μ΄λ―€λ‘œ λ·°κ°€ 사라지면 ν”„λ‘œνΌν‹° μ—­μ‹œ 사라진닀. 

 

μ΄λŸ¬ν•œ 문제λ₯Ό ν•΄κ²°ν•΄μ£ΌλŠ” 것이 Observable 객체닀.

μ•žμ„œ λ§ν•œ λ¬Έμ œμ λ“€μ„ ν•΄κ²°ν•˜κ³ , λ‹€λ₯Έ λ·°μ—μ„œ μ ‘κ·Όν•  수 μžˆλŠ” 영ꡬ적인 데이터λ₯Ό ν‘œν˜„ν•˜κΈ° μœ„ν•΄ μ‚¬μš©ν•œλ‹€.

 

Observable 객체

μ•„λž˜ μ½”λ“œμ™€ λΉŒλ“œλœ 앱을 보면 @Binding ν”„λ‘œνΌν‹° 래퍼λ₯Ό μ‚¬μš©ν•΄μ„œ, νŽ˜μ΄μ§€κ°€ λ³€κ²½λ˜μ–΄λ„ ν•˜λ‚˜μ˜ 값을 κ°€λ₯΄ν‚€κ³  이λ₯Ό λ³€κ²½ν•˜κ³  μžˆλ‹€.

struct ContentView: View {
    @State private var number: Int = 0
    
    var body: some View {
        NavigationView {
            VStack {
                Text("\(self.number)")
                
                Button(action: {
                    self.number += 1
                }) {
                    Text("λˆŒλŸ¬μ£Όμ„Έμš”!")
                }
                
                SubView(number: $number)
                
                
                NavigationLink(destination: SecondView(number: $number)) {
                    Text("Second View둜 이동")
                }
            }
        }
    }
}

struct SubView: View {
    @Binding var number: Int
    
    var body: some View {
        VStack {
            Text("This is SubView")
            Text("\(self.number)")
            
            Button(action: {
                self.number += 1
            }) {
                Text("λˆŒλŸ¬μ£Όμ„Έμš”!")
            }
        }
        .padding()
        .background(.gray)
    }
}

struct SecondView: View {
    @Binding var number: Int
    
    var body: some View {
        VStack {
            Text("This is Second View")
            Text("\(self.number)")
            
            Button(action: {
                self.number += 1
            }) {
                Text("λˆŒλŸ¬μ£Όμ„Έμš”!")
            }
        }
        .padding()
        .background(.gray)
    }
}

ν•˜μ§€λ§Œ 메인 λ·° 내뢀에 Second Viewκ°€ μ’…μ†μ μœΌλ‘œ μ„ μ–Έλ˜μ–΄ 있고, 맀번 @Bindingλ₯Ό 달아쀀 ν”„λ‘œνΌν‹°λ₯Ό μ„ μ–Έν•΄μ•Ό ν•œλ‹€.

 

λ‹¨μˆœνžˆ ν•˜λ‚˜μ˜ νŽ˜μ΄μ§€(λΆ€λͺ¨)의 ν”„λ‘œνΌν‹°λ₯Ό λ‹€λ₯Έ νŽ˜μ΄μ§€(μžμ‹)μ—μ„œ μ‚¬μš©ν•˜λŠ” κ²½μš°μ—λŠ” κΈ°μ‘΄ λ°©μ‹λŒ€λ‘œ @Binding으둜 전달해도 λ˜μ§€λ§Œ, νŽ˜μ΄μ§€ 이동이 μž¦μ•„μ§€λ©΄ 맀번 직접 μ—°κ²°ν•΄μ€˜μ•Ό ν•˜λ―€λ‘œ λ²ˆκ±°λ‘­λ‹€.

 

이런 λ¬Έμ œλ“€μ„ Observable이 ν•΄κ²°ν•΄μ€€λ‹€.

ViewModelκ³Ό λΉ„μŠ·ν•œ 역할을 μˆ˜ν–‰ν•˜λŠ”λ°, νŠΉμ • 상황에 따라 λ³€κ²½λ˜λŠ” 데이터λ₯Ό μˆ˜μ§‘ν•˜κ³  κ΄€λ¦¬ν•˜λŠ” 역할을 μˆ˜ν–‰ν•œλ‹€κ³  λ³Ό 수 μžˆλ‹€.

 

Observable κ°μ²΄λŠ” Observer 객체와 ν•˜λ‚˜μ˜ μ„ΈνŠΈλ₯Ό 이룬닀.

Observable κ°μ²΄λŠ” ν”„λ‘œνΌν‹°λ₯Ό κ²Œμ‹œ(Publish)ν•˜κ³  Observer κ°μ²΄λŠ” 이λ₯Ό κ΅¬λ…ν•˜κ³  μžˆλ‹€.

import Foundation
import Combine

class CustomNumber: ObservableObject {
    @Published var number = 0
    
    func increateNumber() {
        self.number += 1
    }
}
struct ContentView: View {
    @ObservedObject var number: CustomNumber
    
    var body: some View {
        NavigationView {
            VStack {
                Text("\(self.number.number)")
                
                Button(action: {
                    self.number.increateNumber()
                }) {
                    Text("λˆŒλŸ¬μ£Όμ„Έμš”!")
                }
                
                SubView(number: number)
                
                NavigationLink(destination: SecondView(number: number)) {
                    Text("Second View둜 이동")
                }
            }
        }
    }
}

struct SubView: View {
    @ObservedObject var number: CustomNumber
    
    var body: some View {
        VStack {
            Text("This is SubView")
            Text("\(self.number.number)")
            
            Button(action: {
                self.number.increateNumber()
            }) {
                Text("λˆŒλŸ¬μ£Όμ„Έμš”!")
            }
        }
        .padding()
        .background(.gray)
    }
}

struct SecondView: View {
    @ObservedObject var number: CustomNumber
    
    var body: some View {
        VStack {
            Text("This is Second View")
            Text("\(self.number.number)")
            
            Button(action: {
                self.number.increateNumber()
            }) {
                Text("λˆŒλŸ¬μ£Όμ„Έμš”!")
            }
        }
        .padding()
        .background(.gray)
    }
}

기쑴에 @Binding으둜 μž‘μ„±ν•œ μ½”λ“œμ™€ 비ꡐ해보면 number 증가에 λŒ€ν•œ λ‘œμ§μ„ ObservableObject ν”„λ‘œν† μ½œμ„ μ±„νƒν•œ CustomNumberμ—μ„œ λ‹΄λ‹Ήν•˜κ³  μžˆλŠ” 것을 λ³Ό 수 μžˆλ‹€.

 

Environment 객체

number 증가에 λŒ€ν•œ λ‘œμ§μ„ CustomNumber 클래슀둜 λΆ„λ¦¬ν–ˆμ§€λ§Œ μ—¬μ „νžˆ Navigation을 μ§„ν–‰ν•  λ•Œ ꡬ독 객체에 λŒ€ν•œ 참쑰체λ₯Ό 전달해야 ν•œλ‹€.

상황에 따라 λ‹€λ₯΄μ§€λ§Œ μ•± λ‚΄μ˜ μ—¬λŸ¬ λ·°κ°€ λ™μΌν•œ ꡬ독 객체에 μ ‘κ·Όν•΄μ•Όν•˜λŠ” κ²½μš°μ—λŠ” λ³΅μž‘ν•΄μ§ˆ 수 μžˆλ‹€.

 

이럴 λ•Œ μ‚¬μš©ν•˜λŠ” 것이 Environment 객체닀.

방법은 Observable 객체와 λ™μΌν•˜μ§€λ§Œ λ·°μ—μ„œ 뷰둜 전달할 ν•„μš” 없이 λͺ¨λ“  λ·°κ°€ μ ‘κ·Όν•  수 μžˆλ‹€λŠ” 것이닀. 

import SwiftUI

@main
struct _21024_ObservableApp: App {
    let customNumber: CustomNumber = CustomNumber()
    
    var body: some Scene {
        WindowGroup {
            ContentView().environmentObject(customNumber)
        }
    }
}

ν•˜μ§€λ§Œ μ‚¬μš©ν•˜κΈ° 전에 Senceμ—μ„œ 각각의 λ·°μ—μ„œ μ°Έμ‘°ν•˜λ €λŠ” ObservableObjectλ₯Ό λ“±λ‘ν•΄μ€˜μ•Ό ν•œλ‹€.

 

struct ContentView: View {
    @EnvironmentObject var number: CustomNumber
    
    var body: some View {
        NavigationView {
            VStack {
                Text("\(self.number.number)")
                
                Button(action: {
                    self.number.increateNumber()
                }) {
                    Text("λˆŒλŸ¬μ£Όμ„Έμš”!")
                }
                
                SubView()
                
                NavigationLink(destination: SecondView()) {
                    Text("Second View둜 이동")
                }
            }
        }
    }
}

struct SubView: View {
    @EnvironmentObject var number: CustomNumber
    
    var body: some View {
        VStack {
            Text("This is SubView")
            Text("\(self.number.number)")
            
            Button(action: {
                self.number.increateNumber()
            }) {
                Text("λˆŒλŸ¬μ£Όμ„Έμš”!")
            }
        }
        .padding()
        .background(.gray)
    }
}

struct SecondView: View {
    @EnvironmentObject var number: CustomNumber
    
    var body: some View {
        VStack {
            Text("This is Second View")
            Text("\(self.number.number)")
            
            Button(action: {
                self.number.increateNumber()
            }) {
                Text("λˆŒλŸ¬μ£Όμ„Έμš”!")
            }
        }
        .padding()
        .background(.gray)
    }
}

κΈ°μ‘΄ 방식과 λ‹€λ₯΄κ²Œ 뷰와 λ·° 사이 간에 Navigation을 μ§„ν–‰ν•  λ•Œ λ§€κ°œλ³€μˆ˜λ‘œ λ„˜κ²¨μ£Όμ§€ μ•Šμ•„λ„ λœλ‹€λŠ” μž₯점이 μžˆλ‹€.

 

사싀 @State, @Binding, @ObservedObject, @EnvironmentObject 쀑에 μ–΄λŠ 것을 μ“Έ μ§€λŠ” 개발자 마음이고 μ–΄λ–»κ²Œ κ΅¬ν˜„ν•˜λŠλƒμ— 따라 달라진닀고 μƒκ°ν•œλ‹€.

κ·Έλž˜λ„ 각 ν”„λ‘œνΌν‹° λž˜νΌλ³„λ‘œ μž₯점이 μžˆμœΌλ‹ˆ, μž₯점에 맞게 μ‚¬μš©ν•˜λ©΄ 될 λ“―ν•˜λ‹€.

 

정리

ν•˜λ‚˜μ˜ λ·°, ν˜Ήμ€ νŠΉμ • 뷰의 쒅속적인 λ·°μ—μ„œ 단방ν–₯으둜 데이터λ₯Ό μ£Όκ³  받을 λ•Œ -> @State

μ–‘λ°©ν–₯으둜 데이터λ₯Ό μ£Όκ³  받을 λ•Œ -> @Binding

μ–‘λ°©ν–₯으둜 μ£Όκ³  λ°›μœΌλ©΄μ„œ, λ‘œμ§μ„ λΆ„λ¦¬ν•˜κ³  싢을 λ•Œ -> @ObservedObject

λͺ¨λ“  λ·°μ—μ„œ μ°Έμ‘°ν•  수 μžˆλŠ” 데이터와 λ‘œμ§μ„ λΆ„λ¦¬ν•˜κ³  싢을 λ•Œ -> @EnvironmentObject

 

πŸ‘€ 회고

Environment 객체의 경우 Flutter의 Provider와 맀우 μœ μ‚¬ν•œ ν˜•νƒœλ₯Ό μ§€λ…”λ‹€. Providerλ₯Ό 톡해 ν•˜μœ„ μœ„μ ―μ—μ„œ 데이터λ₯Ό μ ‘κ·Όν•  수 μžˆλŠ”λ° 이것과 μ™„μ „νžˆ λ˜‘κ°™μ•˜λ‹€. ν•œ κ°€μ§€ κΆκΈˆν•œ 점은 Flutterμ—μ„œλŠ” κ°’μ˜ 변경이 μΌμ–΄λ‚˜λ©΄ ν•΄λ‹Ή μœ„μ ―μ„ μ „λΆ€ λ‹€μ‹œ λ Œλ”λ§μ„ μ§„ν–‰ν•œλ‹€. (Consumerλ₯Ό μ μš©ν•΄μ„œ νŠΉμ • λΆ€λΆ„ λ Œλ”λ§λ„ κ°€λŠ₯ν•˜λ‹€.)  SwiftUIμ—μ„œλŠ” 자체적으둜 νŠΉμ • λΆ€λΆ„λ§Œ λ Œλ”λ§μ„ ν•˜λŠ”κ±΄μ§€ μ „λΆ€ λ Œλ”λ§μ„ μ§„ν–‰ν•˜λŠ” 것인지 μ’€ 더 μ•Œμ•„λ΄μ•„κ² λ‹€.

μ €μž‘μžν‘œμ‹œ λΉ„μ˜λ¦¬ λ³€κ²½κΈˆμ§€ (μƒˆμ°½μ—΄λ¦Ό)

'πŸ’» 개발 > iOS' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

[iOS / SwiftUI] 슀크둀, λ¬΄ν•œμœΌλ‘œ μ¦κ²¨μš”~ (LazyVStack으둜 λ¬΄ν•œ 슀크둀 κ΅¬ν˜„ν•˜κΈ°)  (0) 2022.11.28
[iOS / Swift] Swift λ¬Έμžμ—΄ μ •λ³΅ν•˜κΈ° (aka 'Character')  (0) 2022.11.03
[iOS / SwiftUI] ν‚€λ³΄λ“œκ°€ 사라지지 μ•Šμ•„μš”...😩  (0) 2022.10.21
[iOS / SwiftUI] ForEach둜 Viewλ₯Ό λ¦¬νŽ™ν† λ§ ν•΄λ³ΌκΉŒμš”?  (0) 2022.10.11
[iOS / Swift] lim ν΄λ‘œμ € -> 0 (ν΄λ‘œμ €, κ·Ήν•œμœΌλ‘œ 쀄여보기)  (0) 2022.10.05
  1. State와 Binding
  2. Observable 객체
  3. Environment 객체
  4. 정리
  5. πŸ‘€ 회고
'πŸ’» 개발/iOS' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€
  • [iOS / SwiftUI] 슀크둀, λ¬΄ν•œμœΌλ‘œ μ¦κ²¨μš”~ (LazyVStack으둜 λ¬΄ν•œ 슀크둀 κ΅¬ν˜„ν•˜κΈ°)
  • [iOS / Swift] Swift λ¬Έμžμ—΄ μ •λ³΅ν•˜κΈ° (aka 'Character')
  • [iOS / SwiftUI] ν‚€λ³΄λ“œκ°€ 사라지지 μ•Šμ•„μš”...😩
  • [iOS / SwiftUI] ForEach둜 Viewλ₯Ό λ¦¬νŽ™ν† λ§ ν•΄λ³ΌκΉŒμš”?
kodo_o
kodo_o
iOS κΏ€μžΌ!
kodo_o
🍎🍏
kodo_o
전체
였늘
μ–΄μ œ
  • λΆ„λ₯˜ 전체보기 (149)
    • πŸ”¨ ν”„λ‘œμ νŠΈ (0)
      • TP 1 (0)
      • WhiteHCCTV (0)
      • FootPrint (0)
    • πŸ’» 개발 (63)
      • iOS (30)
      • Android (6)
      • Kotlin (4)
      • Flutter (9)
      • Node.js (5)
      • Architecture (1)
      • 였늘의 μ‚½μ§ˆ (7)
      • μ—λŸ¬μ™€μ˜ 동침 (1)
    • ✏️ μ•Œκ³ λ¦¬μ¦˜ (6)
      • Graph (6)
      • String (0)
      • Sort (0)
    • ✍️ μ½”ν…Œ μ€€λΉ„ (44)
      • Math (1)
      • Implementation (3)
      • String (3)
      • Brute Force (5)
      • Back Tracking (7)
      • Greedy (0)
      • Dynamic Programming (13)
      • Binary Search (1)
      • DFS, BFS (5)
      • Shortest Path (2)
      • Two Pointer (4)
      • MST (0)
    • πŸ“š CS (6)
      • Operating System (6)
    • ⛹️ 라이프 (30)
      • 2020 κ²¨μšΈλ°©ν•™ λͺ¨κ°μ½”(개인) (12)
      • 2021 여름방학 λͺ¨κ°μ½”(개인) (6)
      • μ½”λ”© ν…ŒμŠ€νŠΈ (1)
      • 회고 (10)

λΈ”λ‘œκ·Έ 메뉴

  • ν™ˆ
  • κΉƒν—ˆλΈŒ

인기 κΈ€

졜근 κΈ€

졜근 λŒ“κΈ€

hELLO Β· Designed By μ •μƒμš°.
kodo_o
[iOS / SwiftUI] λ‹€μ–‘ν•œ μƒνƒœ ν”„λ‘œνΌν‹°λ“€μ„ μ•Œμ•„λ³΄μž!
μƒλ‹¨μœΌλ‘œ

ν‹°μŠ€ν† λ¦¬νˆ΄λ°”

단좕킀

λ‚΄ λΈ”λ‘œκ·Έ

λ‚΄ λΈ”λ‘œκ·Έ - κ΄€λ¦¬μž ν™ˆ μ „ν™˜
Q
Q
μƒˆ κΈ€ μ“°κΈ°
W
W

λΈ”λ‘œκ·Έ κ²Œμ‹œκΈ€

κΈ€ μˆ˜μ • (κΆŒν•œ μžˆλŠ” 경우)
E
E
λŒ“κΈ€ μ˜μ—­μœΌλ‘œ 이동
C
C

λͺ¨λ“  μ˜μ—­

이 νŽ˜μ΄μ§€μ˜ URL 볡사
S
S
맨 μœ„λ‘œ 이동
T
T
ν‹°μŠ€ν† λ¦¬ ν™ˆ 이동
H
H
단좕킀 μ•ˆλ‚΄
Shift + /
⇧ + /

* λ‹¨μΆ•ν‚€λŠ” ν•œκΈ€/영문 λŒ€μ†Œλ¬Έμžλ‘œ 이용 κ°€λŠ₯ν•˜λ©°, ν‹°μŠ€ν† λ¦¬ κΈ°λ³Έ λ„λ©”μΈμ—μ„œλ§Œ λ™μž‘ν•©λ‹ˆλ‹€.