[머릿말]
List, OutlineGroup과 DisclosureGroup에 대해 공부하던 중 이것들의 차이점에 대해 궁금해졌다. 자식 데이터에 대한 계층적 구조를 가진 뷰를 만드는 공통점에 반해 차이점은 무엇인지 말이다.
결론부터 말하자면 OutlineGroup은 자식 데이터(children)가 있는 경우 알아서 그에 대한 계층적 뷰를 생성하여 보여준다. 그러나 DisclosureGroup은 계층적 뷰를 만들기 위해선 직접 작성해야 한다는 차이점이 존재한다.
즉, OutlineGroup은 계층적 구조를 가지는 데이터에 대한 뷰를 자동으로 만들어 주는 것이고, DisclosureGroup은 계층적 뷰를 만들 수 있는 껍데기(?)라고 할 수 있는 것이다.
● OutlineGroup 이란?
공식 문서에서의 내용은 다음과 같다.
"트리 구조, 식별된 데이터의 기본 컬렉션에서 필요에 따라 views와 disclosure groups를 계산하는 구조체"
여기서 말하는 '필요에 따라'는 '자식 데이터의 유무에 따라'로 해석해볼 수 있다. 즉, 트리 구조에서 자식 데이터가 있으면 알아서 이를 계산하여 뷰로 만들어 준다는 것이다.
- 예제)
import SwiftUI
struct CarInfo: Identifiable {
var id = UUID()
var name: String
var children: [CarInfo]?
}
let carData: [CarInfo] = [
CarInfo(name: "국산차", children: [
CarInfo(name: "현대", children: [
CarInfo(name: "세단", children: [
CarInfo(name: "그랜저"),
CarInfo(name: "쏘나타"),
CarInfo(name: "아반떼")
]),
CarInfo(name: "SUV", children: [
CarInfo(name: "펠리세이드"),
CarInfo(name: "싼타페"),
CarInfo(name: "투싼")
])
]),
CarInfo(name: "기아", children: [
CarInfo(name: "세단", children: [
CarInfo(name: "K8"),
CarInfo(name: "K5"),
CarInfo(name: "K3")
]),
CarInfo(name: "SUV", children: [
CarInfo(name: "모하비"),
CarInfo(name: "쏘렌토"),
CarInfo(name: "스포티지")
])
])
])
]
struct ContentView: View {
var body: some View {
List {
OutlineGroup(carData, children: \.children) { car in
Text(car.name)
}
}
}
}
#Preview {
ContentView()
}
예시로 사용할 데이터가 필요하므로 계층적 구조를 나타내기에 적절한 소재인 자동차를 사용하였다.
CarInfo 는 자동차의 데이터 타입을 나타내는 구조체인데 OutlineGroup에 사용할 데이터는 Identifiable 프로토콜을 준수해야 하는 것에 주의해야 한다.
carData 는 CarInfo 타입의 배열인데 계층적 구조를 갖고 있음을 확인할 수 있다.
ContentView 부분을 보면 단순 List와 OutlineGroup만을 사용한 것을 볼 수 있다. 그러나 OutlineGroup을 사용했기에 자식 데이터가 있는 경우 알아서 계층적 구조를 만든 것을 확인할 수 있다.
● DisclosureGroup 이란?
공식 문서에서의 내용은 다음과 같다.
"disclosure control의 상태에 기반하여 다른 content view를 보이거나 숨기는 뷰"
여기서 disclosure control은 뷰가 확장 또는 축소되어 있는지를 나타내는 것이라고 보면 된다. 위 내용에 따르면 이는 그저 여러 Content에 대한 계층적 뷰를 만들어 준다는 것을 알 수 있다.
- 예제)
import SwiftUI
struct CarInfo: Identifiable {
var id = UUID()
var name: String
var children: [CarInfo]?
}
let carData: [CarInfo] = [
CarInfo(name: "국산차", children: [
CarInfo(name: "현대", children: [
CarInfo(name: "세단", children: [
CarInfo(name: "그랜저"),
CarInfo(name: "쏘나타"),
CarInfo(name: "아반떼")
]),
CarInfo(name: "SUV", children: [
CarInfo(name: "펠리세이드"),
CarInfo(name: "싼타페"),
CarInfo(name: "투싼")
])
]),
CarInfo(name: "기아", children: [
CarInfo(name: "세단", children: [
CarInfo(name: "K8"),
CarInfo(name: "K5"),
CarInfo(name: "K3")
]),
CarInfo(name: "SUV", children: [
CarInfo(name: "모하비"),
CarInfo(name: "쏘렌토"),
CarInfo(name: "스포티지")
])
])
])
]
struct ContentView: View {
var body: some View {
Form {
DisclosureGroup {
// 현대
DisclosureGroup {
DisclosureGroup {
Text(carData[0].children![0].children![0].children![0].name)
Text(carData[0].children![0].children![0].children![1].name)
Text(carData[0].children![0].children![0].children![2].name)
} label: { Text(carData[0].children![0].children![0].name)}
DisclosureGroup {
Text(carData[0].children![0].children![1].children![0].name)
Text(carData[0].children![0].children![1].children![1].name)
Text(carData[0].children![0].children![1].children![2].name)
} label: { Text(carData[0].children![0].children![1].name)}
} label: { Text(carData[0].children![0].name) }
// 기아
DisclosureGroup {
DisclosureGroup {
Text(carData[0].children![1].children![0].children![0].name)
Text(carData[0].children![1].children![0].children![1].name)
Text(carData[0].children![1].children![0].children![2].name)
} label: { Text(carData[0].children![1].children![0].name)}
DisclosureGroup {
Text(carData[0].children![1].children![1].children![0].name)
Text(carData[0].children![1].children![1].children![1].name)
Text(carData[0].children![1].children![1].children![2].name)
} label: { Text(carData[0].children![1].children![1].name)}
} label: { Text(carData[0].children![1].name) }
} label: { Text(carData[0].name) }
}
}
}
#Preview {
ContentView()
}
앞서 List와 OutlineGroup을 사용하여 만들었던 예제를 Form과 DisclosureGroup을 사용하여 만들어 보았다. 이를 실제로 이렇게 사용하는 경우는 없겠지만 두 개의 차이를 뚜렷하게 확인하고자 만들어 본 것이다. 이제 DisclosureGroup은 계층적 구조를 나타낼 수 있는, 하위 요소들을 펼치거나 숨길 수 있는 껍데기(?)의 역할을 한다는 것을 이해할 수 있을 것이다.
책을 보며 공부하다가 비슷한 역할을 하는 두 개념을 접하면 차이점이 무엇인지, 각각 어느 경우에 사용하는지에 포커스를 맞추고 있다.
매번 느끼는 것인데 글로 작성하는 것은 적지 않은 시간이 소모되지만 그만큼의 충분한 가치가 있는 것 같다.
다들 화이팅입니다!
-끝-
'[Programming Language] > [SwiftUI]' 카테고리의 다른 글
[SwiftUI] 앱 아이콘(Icon) 설정 방법 (1) | 2024.10.15 |
---|---|
[SwiftUI] TabView란? 사용 예시, 배경색 및 아이템 색 변경 등 (0) | 2024.10.14 |
[SwiftUI] Deprecated 되어버린 cornerRadius를 대체할 방법 (2) | 2024.10.13 |
[SwiftUI] @SceneStorage(화면 저장소) vs @AppStorage(앱 저장소) (0) | 2024.10.12 |
[SwiftUI] Deprecated된 tabItem(_:)을 대신하여 Tab()을 사용할 수 있다 (5) | 2024.10.06 |