SwiftUI

View Identity와 transition 관계

Phililip
728x90

안녕하세요.

 

이번에는 SwiftUI에서 View의 identity와 transition이 어떤 관계에 있으며 어떻게 화면이 렌더링 되는지에 대해 알아볼게요.

 


SwiftUI View의 identity는 2가지가 있어요.

 

  • structual identity: View 계층에서 type과 위치에 따라 구분되는 암시적인 identity
  • explicit identity: id 수식어를 사용해서 명시적으로 identity 선언

 

 

이런 Identity는 transition과 밀접한 관계를 가지고 있습니다.

(View의 identity가 바뀔 때, transition이 동작하게 됩니다.)

 

 

structual identity와 explicit idenity 별로 transition이 어떻게 동작하는지 알아볼게요.

 

 

 

## Structual identity

View 내부의 값이 바뀌더라도 View 자체의 structual identity는 변하지 않습니다.

 

아래의 예시를 볼까요?

struct ContentView: View {
    @State private var count: Int = 0
    
    var body: some View {
        VStack {
            SubView(count: count)
                .transition(.move(edge: .leading))  🤔
            Button {
                withAnimation {
                    count += 1
                }
            } label: {
                Text("Increment")
            }

        }
    }
}

struct SubView: View {
    let count: Int
    var body: some View {
        RoundedRectangle(cornerRadius: 6)
            .foregroundColor(.yellow)
            .frame(width: 100, height: 100)
            .overlay(
                Text("\(count)")
                    .monospacedDigit()
                    .padding()
            )
    }
}

 

버튼을 누를 때마다 count 값이 바뀌게 되고, 그때마다 SubView가 다시 그려질 것이라고 예상해서 기존 SubView가 옆으로 사라지도록 transition을 넣어줬어요.

 

기대한 것처럼 잘 나오는지 한번 볼까요?

 

 

 

 

버튼이 누를 때마다 값이 바뀌긴 하지만, transition이 적용되지 않았습니다..

 

이 말은 'SubView의 Structual Identity가 동일하게 유지가 된다!' 라고 볼 수 있어요.

 

 

 

만약 지금 상태에서 transition이 적용되도록 하고 싶으면 어떻게 해야 할까요?

 

많은 방법들이 있지만.. 분기문을 통해서 View의 identity를 나눠주는 것도 좋은 방법이 될 것입니다ㅎㅎ

struct ContentView: View {
    @State private var count: Int = 0
    
    var body: some View {
        VStack {
            Group {    ✅
                if count % 2 == 0 {
                    SubView(count: count)
                        .transition(.move(edge: .leading))
                } else {
                    SubView(count: count)
                        .transition(.move(edge: .leading))
                }
            }
            
            Button {
                withAnimation {
                    count += 1
                }
            } label: {
                Text("Increment")
            }

        }
    }
}

struct SubView: View {
    let count: Int
    var body: some View {
        RoundedRectangle(cornerRadius: 6)
            .foregroundColor(.yellow)
            .frame(width: 100, height: 100)
            .overlay(
                Text("\(count)")
                    .monospacedDigit()
                    .padding()
            )
    }
}

 

 

 

structual identity는 'identity가 동일한지? 그래서 transition이 적용되는지?' 가 한눈에 안 보이는 단점이 있어요.

 

 

 

## Explicit identity

이번에는 명시적으로 identity를 설정해줄게요.

 

id 수식어를 사용해서 identity를 직접 설정해줄 수 있어요.

 

Hashable 한 값들만 identity로 설정할 수 있습니다!!

func id<ID>(_ id: ID) -> some View where ID : Hashable

 

 

이번에는 SubView에 id를 직접 선언해줘 볼게요.

struct ContentView: View {
    @State private var count: Int = 0
    
    var body: some View {
        VStack {
            SubView(count: count)
                .id(count)    ✅
                .transition(.move(edge: .leading))
            Button {
                withAnimation {
                    count += 1
                }
            } label: {
                Text("Increment")
            }

        }
    }
}

struct SubView: View {
    let count: Int
    var body: some View {
        RoundedRectangle(cornerRadius: 6)
            .foregroundColor(.yellow)
            .frame(width: 100, height: 100)
            .overlay(
                Text("\(count)")
                    .monospacedDigit()
                    .padding()
            )
    }
}

 

 

count가 변경됨에 따라 SubView의 identity도 변경되니 transition이 잘 적용되는 것을 볼 수 있습니다.ㅎㅎ

 

 

 

 

이렇게 명시적으로 identity를 설정하는 경우, identity가 잘못된 경우에는 transition이 이상하게 동작할 수 있으니 유의해줘야 합니다.

 

 

 

## 참고

- https://sakunlabs.com/blog/swiftui-identity-transitions/

 

SwiftUI: Understanding identity via transitions

There is a lot to learn about identity in SwiftUI. One way to go about it is to understand the role of identity in transitions.

sakunlabs.com

 

 


 

이번 글은 여기서 마무리.

 

 

 

반응형

'SwiftUI' 카테고리의 다른 글

@FocusState  (0) 2022.12.11
텍스트 길이에 맞춰서 자식뷰의 width를 통일시키는 방법  (0) 2022.06.18
TimelineView  (0) 2022.06.17
trim  (0) 2022.06.06
PreferenceKey  (0) 2022.05.30