SwiftUI

SwiftUI - @Binding

iosos 2023. 8. 25. 21:35

@Binding

- SwiftUI에서 사용되는 프로퍼티 래퍼(wrapper) 중 하나로, 데이터의 양방향 바인딩을 생성하는 데 사용

- '@Binding' 을 사용하면 부모 뷰로부터 전달된 데이터를 자식 뷰에서 수정할 수 있음 

- 보통 부모 뷰에서 자식 뷰로 데이터를 전달할 때, 데이터는 일방향을 전달됨

부모 뷰에서 자식 뷰로 데이터를 전달하고 나면, 자식 뷰에서 그 데이터를 수정하여 다시 부모 뷰로 전달하기 위해선 추가 작업이 필요

→ '@Binding'을 사용하면 부모 뷰와 자식 뷰 간의 데이터 흐름을 양방향으로 만듦

즉, 부모 뷰로부터 받은 데이터를 자식 뷰에서 변경하면 부모 뷰에서도 자동 변경 

 

@State 관련 게시물 코드를 이용함   2023.08.19 - [분류 전체보기] - SwiftUI - @State

 

 

 


바인딩 설정 (자식 뷰)

'isActivated' 라는 바인딩을 사용하여 배경색과 패딩을 동적으로 변경

struct newView : View {
    
    // 데이터 연동
    @Binding
    var isActivated: Bool
    
    // 생성자
    init(isActivated: Binding<Bool> = .constant(false)){
        _isActivated = isActivated
    }
    
    var body: some View{
        HStack{
            Text("1!")
                .foregroundColor(.blue)     // 글자색 지정
                .bold()                     // 글자 두껍게
                .font(.system(size: 40))    // 글자 사이즈 지정
            
            Text("2!")
                .foregroundColor(.blue)
                .bold()
                .font(.system(size: 40))
            
            Text("3!")
                .foregroundColor(.blue)
                .bold()
                .font(.system(size: 40))
        } // HStack
        .background(self.isActivated  ? .green : .red)   // isActivated가 true이면 green, false이면 red
        .padding(self.isActivated ? 30 : 10)        //isActivated가 true이면 30, false이면 10
    } // View
}

- 'isActivated'는 부모 뷰로부터 전달된 바인딩

- 'init(_ : Binding<T>)' 생성자를 이용하여 'isActivated' 바인딩을 초기화 

- 생성자의 기본값으로 '.constant(false)'을 사용하여 기본적으로 false 값을 가지게 됨 

- 마지막으로 'isActivated' 바인딩 값에 따라 HStack의 배경색과 패등을 설정 

 

 

 

 

부모 뷰

struct Tutorial: View {
    
    // @State : 값의 변화를 감지하고 뷰에 적용
    @State private var isActivated : Bool = false
    
    var body: some View {
        
        NavigationView{
            VStack{
                VStack{
                    
                    newView(isActivated: $isActivated)
                    newView(isActivated: $isActivated)
                    newView(isActivated: $isActivated)
                    
                } // VStack
                
               ......

- 자식 뷰인 'newView'를 가져올 때 'newView'는 'isActivated' 바인딩을 전달해줘야 함 

- '$isActivated' : 'isActivated' 변수에 대한 바인딩을 생성하는 역할

- 생성된 바인딩은 'newView' 내부에서 'isActivated' 값을 읽거나 변경하는 데 사용 

 

 

 

 

 

 

네비게이션 뷰로 이동할 때의 바인딩

이동할 뷰 

// 이동할 뷰
struct myTextView : View{
    
    // 데이터 연동
    @Binding
    var isActivated: Bool
    
    // 생성자
    init(isActivated: Binding<Bool> = .constant(false)){
        _isActivated = isActivated
    }
    
    
    // 배경색 배열 인덱스
    @State var index = 0
    
    // 배경색 배열
    let backgroundColorArray = [Color.red, Color.blue, Color.green, Color.yellow, Color.brown]
    
    
    var body: some View{
        VStack{
            
            // 공간 추가
            Spacer()
            
            Text("배경 아이템 인덱스 \(self.index)")
                .font(.system(size: 30))
                .fontWeight(.bold)
            
                // 배경을 전체로 설정
                .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 100)
            
            Text("isActivated : \(String(self.isActivated))")
                .font(.system(size: 30))
                .fontWeight(.bold)
                .foregroundColor(self.isActivated ? .yellow : .gray)
                .background(.black)
            
            Spacer()
            
            
        }
        
        .......

- '@Binding' 설정 및 초기화 

- Text를 추가하여 바인딩된 'isActivated'를 String으로 바꾸어 화면에 출력 

- 'isActivated'의 값이 true이면 배경색이 노란색, false이면 회색으로 설정 

 

 

 

부모 뷰 

     ......
                // destination : 이동하고자 하는 뷰
                NavigationLink(destination: myTextView(isActivated: $isActivated)){
                    Text("네비게이션")
                        .fontWeight(.heavy)
                        .font(.system(size:30))
                        .padding()
                        .background(.yellow)
                        .foregroundColor(.white)
                        .cornerRadius(30)
                }
                .padding(30)
                
                
                ......

- NavigationLink를 통해 이동하고자 하는 뷰인 'myTextView'를 호출할 때 'isActivated' 값을 바인딩함 

 

 

 

 

 

전체 코드

메인 뷰

import SwiftUI

struct Tutorial: View {
    
    // @State : 값의 변화를 감지하고 뷰에 적용
    @State private var isActivated : Bool = false
    
    var body: some View {
        
        NavigationView{
            VStack{
                VStack{
                    
                    newView(isActivated: $isActivated)
                    newView(isActivated: $isActivated)
                    newView(isActivated: $isActivated)
                    
                } // VStack
                
                // isAcitved가 true이면 50, false면 10으로 패딩 지정
                .padding(isActivated ? 50 : 10)
                
                // isAcitved가 true이면 .yellow, false면 .green
                .background(isActivated ? .yellow : .green)
                
                // 탭 제스처 추가
                .onTapGesture {
                    
                    // 애니메이션 추가
                    withAnimation{
                        
                        // toggle() true이면 false로 false면 true로 변경
                        self.isActivated.toggle()
                    }
                }
                
                // destination : 이동하고자 하는 뷰
                NavigationLink(destination: myTextView(isActivated: $isActivated)){
                    Text("네비게이션")
                        .fontWeight(.heavy)
                        .font(.system(size:30))
                        .padding()
                        .background(.yellow)
                        .foregroundColor(.white)
                        .cornerRadius(30)
                }
                .padding(30)
                
            }
        }   // NavigationView
    }   // body
}

 

 서브 뷰

struct newView : View {
    
    // 데이터 연동
    @Binding
    var isActivated: Bool
    
    // 생성자
    init(isActivated: Binding<Bool> = .constant(false)){
        _isActivated = isActivated
    }
    
    var body: some View{
        HStack{
            Text("1!")
                .foregroundColor(.blue)     // 글자색 지정
                .bold()                     // 글자 두껍게
                .font(.system(size: 40))    // 글자 사이즈 지정
            
            Text("2!")
                .foregroundColor(.blue)
                .bold()
                .font(.system(size: 40))
            
            Text("3!")
                .foregroundColor(.blue)
                .bold()
                .font(.system(size: 40))
        } // HStack
        .background(self.isActivated  ? .green : .red)   // isActivated가 true이면 green, false이면 red
        .padding(self.isActivated ? 30 : 10)        //isActivated가 true이면 30, false이면 10
    } // View
}

 

이동할 뷰

// 이동할 뷰
struct myTextView : View{
    
    // 데이터 연동
    @Binding
    var isActivated: Bool
    
    // 생성자
    init(isActivated: Binding<Bool> = .constant(false)){
        _isActivated = isActivated
    }
    
    
    // 배경색 배열 인덱스
    @State var index = 0
    
    // 배경색 배열
    let backgroundColorArray = [Color.red, Color.blue, Color.green, Color.yellow, Color.brown]
    
    
    var body: some View{
        VStack{
            
            // 공간 추가
            Spacer()
            
            Text("배경 아이템 인덱스 \(self.index)")
                .font(.system(size: 30))
                .fontWeight(.bold)
            
                // 배경을 전체로 설정
                .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 100)
            
            Text("isActivated : \(String(self.isActivated))")
                .font(.system(size: 30))
                .fontWeight(.bold)
                .foregroundColor(self.isActivated ? .yellow : .gray)
                .background(.black)
            
            Spacer()
            
            
        }
        .background(self.backgroundColorArray[self.index])
        
        .onTapGesture {
            // index가 backgroundColorArray의 배열 수보다 커지면 index를 0으로 설정
            if (index == backgroundColorArray.count - 1){
                index = 0
            }
            else{
                index += 1
            }
        } // onTopGesture
    }
}

 

 

 

참고) https://www.youtube.com/watch?v=dCDCmNkKkWk&list=PLgOlaPUIbynqyJHiTEv7CFaXd8g5jtogT&index=3 

'SwiftUI' 카테고리의 다른 글

SwiftUI - SwiftUI 모드로 Xcode 이용  (1) 2024.01.07
SwiftUI - 개요  (0) 2024.01.07
SwiftUI - @State  (0) 2023.08.19
SwiftUI - 튜토리얼  (0) 2023.08.17
SwiftUI - Container Views (VStack, HStack)  (0) 2023.07.28