본문 바로가기

App Dev/iOS

iOS SwiftUI @Binding으로 View 끼리 데이터 공유

반응형

2023.03.09 - [App Dev/iOS] - iOS SwiftUI @State 문법 어떻게 사용하면 될까?

 

iOS SwiftUI @State 문법 어떻게 사용하면 될까?

@State SwiftUI는 속성의 저장소를 관리합니다. 값이 변경되면 SwiftUI는 값에 의존하는 보기 계층 구조의 일부를 업데이트합니다. 상태의 기본 값에 액세스하려면 해당 속성을 사용합니다. 그러나 단

smart-factory-lee-joon-ho.tistory.com

@Binding

바인딩을 사용하여 데이터를 저장하는 속성과 데이터를 표시하고 변경하는 보기 간에 양방향 연결을 만듭니다. 바인딩은 데이터를 직접 저장하는 대신 속성을 다른 곳에 저장된 정보 소스에 연결합니다. 예를 들어 재생과 일시 중지 사이를 전환하는 버튼은 Binding속성 래퍼를 사용하여 부모 보기의 속성에 대한 바인딩을 만들 수 있습니다.

ContentView 에 제일 핵심적으로 그리고 있는 CircleImageView에 Binding을 사용해보겠습니다.

 //데이터 연동
    @Binding
    var isActivated : Bool
    
    //생성자
    init(isActivated: Binding<Bool> = .constant(false)) {
        _isActivated = isActivated
    }

[이게 핵심 코드 입니다]  변수 선언과 해당 변수의 .constant (기초 값) 설정 해주는 생성자를 작성해줍니다.

다른 뷰 페이지에서 받은 값을 인자로 받아 연결해줍니다.

 

 

<CricleImageView>

import SwiftUI

struct CircleImageView : View{
    
    @Binding
    var isActivated : Bool
    
    init(isActivated: Binding<Bool> = .constant(false)) {
        _isActivated = isActivated
    }
    
    
    
    var body: some View{
        //        Image(systemName: "bolt.circle")
        //            .font(.system(size: 200))
        //            .foregroundColor(.yellow)
        //            .shadow(color: .gray, radius: 2, x: 0, y:10)
        Image("myimage").resizable()
            .scaledToFill()
//            .aspectRatio(contentMode: .fill)
            .frame(width: 200, height: 200)
            .clipShape(Circle())
            // color는 항상 맨 앞으로 !
            .shadow(color: .black ,radius: 10,x:0,y:10)
            .overlay(Circle().foregroundColor(.black).opacity(0.4))
            .overlay(Circle().stroke(Color.red,lineWidth: 10).padding())
            .overlay(Circle().stroke(Color.yellow,lineWidth: 10).padding(30))
            .overlay(Circle().stroke(self.isActivated ? Color.green : Color.blue  ,lineWidth: 10).padding(self.isActivated ? 0 : 45 ))
            .overlay(Text("Joonho").foregroundColor(.white).font(.system(size: 30)).fontWeight(.bold))
//            .clipped()
//            .edgesIgnoringSafeArea(.all)
    }
        
}

struct Previews_CircleimageView_Previews: PreviewProvider {
    static var previews: some View {
        CircleImageView()
    }
}

 

 

.overlay(Circle().stroke) 코드에서 해당 값을 통해 삼항 연산자로 이미지의 변화를 주었습니다.

반응형

<MyTextView>

import SwiftUI

struct MyTextView:View {
    
        // 데이터 연동
        @Binding
        var isActivated: Bool
        
        // 생성자
        init(isActivated: Binding<Bool> = .constant(false)) {
            _isActivated = isActivated
        }
    
    
    //state : 값의 변화를 감지 -> 뷰에 적용
    @State
    private var index : Int = 0
    
    //배경색 배열 준비
    private let backgroubdColors = [
        Color.red,
        Color.yellow,
        Color.blue,
        Color.green,
        Color.orange
    ]
    
    
    var body : some View {
        VStack{
            Spacer()
            
            Text("배경 아이템 인덱스 \(self.index + 1 )")
                .font(.system(size: 30))
                .fontWeight(.bold)
                .frame(minWidth: 0,maxWidth: .infinity,
                       minHeight: 0, maxHeight: 100)
            HStack{
                Text("활성화 상태")
                    .font(.system(size: 30))
                    .foregroundColor(Color.white)
                    .fontWeight(.bold)
                    .background(Color.black)
                    
                Text("\(String(isActivated))")
                    .font(.system(size: 30))
                    .fontWeight(.bold)
                    .foregroundColor(self.isActivated ? Color.green : Color.red)
                    .background(Color.black)
            }
            
            Spacer()
            
        }
        .background(backgroubdColors[index])
        .edgesIgnoringSafeArea(.all)
        .onTapGesture {
            print("배경아이템이 클릭되었다. ")
            
            if(self.index == self.backgroubdColors.count - 1){
                self.index = 0
            }else{
                self.index += 1
            }
        }
    }
    
    struct Previews_MyTextView_Previews: PreviewProvider {
        static var previews: some View {
            MyTextView()
        }
    }
}

해당 페이지에서는 데이터 값을 페이지 화면에 출력해보았습니다.

 

 

<ContentView>

import SwiftUI

struct ContentView: View {
    // @State 값의 변화를 감지 -> 뷰에 적용
    @State
    private var isActivated : Bool = false
    
    var body: some View {
        
       
            NavigationView{
                VStack{
                    HStack{
//                        MyVstackView()
//                        MyVstackView()
                        CircleImageView(isActivated: $isActivated)
                        
                        
                    }
                    .padding(isActivated ? 100.0 :50.0)
                    .background(isActivated ? Color.black : Color.indigo)
                    .cornerRadius(isActivated ? 0 : 20) 
                    // 탭 제스쳐 추가
                    .onTapGesture {
                            print("HStack 클릭 되었다.")
                            //에니메이션과 함께
                            withAnimation{
                                // toggle() true 이면 false 로 false 이면 true
                                self.isActivated.toggle()
                            }
                        }// Hstack
                    
                    // 네비게이션 버튼 (링크)
                    NavigationLink(destination:MyTextView(isActivated: $isActivated)){
                        Text("Navigation")
                            .fontWeight(.bold)
                            .padding()
                            .font(.system(size: 40))
                            .background(Color.green)
                            .foregroundColor(Color.white)
                            .cornerRadius(30)
                        
                        
                        
                    }.padding(.top,50)
                }
                
            }//NavigationView
            
        
}

    
}

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

 

 

 

결국 다른 페이지의 @Binding 값들은 ContentView의 @State private var isActivated 와 연동 된 데이터라고 생각하면 됩니다. 

해당 값을 다른 뷰로 보낼 때는 CircleImageView( 메인뷰 변수 명 : $해당 뷰 Binding 변수 명 )

이렇게 연결해주면 됩니다. 

 

반응형