블로그

ForEach의 ID [SwiftUI]

게시 2분

ForEach View를 사용할 때 ID로 \.self를 넣어주고는 한다.

struct ContentView: View { let colors: [Color] = [.red, .green, .blue] var body: some View { VStack { ForEach(colors, id: \.self) { color in Text(color.description.capitalized) .padding() .background(color) } } } }

ForEach로 생성되는 각 뷰들이 생성되거나 삭제될 때 그 부분만 업데이트하기위해 ID값을 통해서 뷰를 구별한다.

이를 위해서 id인자를 넣어주게 된다.

public init(_ data: Data, id: KeyPath<Data.Element, ID>, @ViewBuilder content: @escaping (Data.Element) -> Content)

ForEach 뷰에 전달하는 id인자는 keyPath로 전달하게 되는데, 참조한 keyPath를 통해

data에서 가져온 값을 unique identifier로 결정지어 각 뷰가 구별되도록한다.

때문에 위 예시에서 \Color.self 를 생략한 \.self를 전달했으므로 각 뷰의 unique identifier는 차례대로.red, .green, .blue가 된다.

그렇다면, data의 각 요소가 같다면 어떻게 해야할까?

예를들어 colors 배열이 다음과 같은 경우를 말한다.

let colors: [Color] = [.red, .red, .blue]

한 스택 오버플로우 답변 에서는 struct 구조체로 감싸서 Identifiable 프로토콜을 준수하도록 함을 권장하고있다.

다음과 같은 구조체를 생성해서 UUID() 함수를 통해 unique identifier을 생성한다.

struct MyColor: Identifiable { var id = UUID() var color: Color }

다음과 같이 keyPath를 .id로 전달해서 각 view가 unique해지도록 한다.

struct ContentView: View { let colors: [MyColor] = [.init(color: .red), .init(color: .red), .init(color: .blue)] var body: some View { VStack { ForEach(colors, id: \.id) { myColor in Text(myColor.color.description.capitalized) .padding() .background(myColor.color) } } } }

댓글

댓글을 남기면 닉네임(또는 GitHub 계정 정보)이 저장됩니다. 개인정보처리방침

GitHub