- 이번에는 SwiftUI에서 List를 어떻게 만들고 다루는지 알아보겠습니다.
리스트(List) 란
- List는 이름 그대로 목록(List) 인터페이스를 구현하기 위해 존재합니다.
- SwiftUI의 리스트는 UIKit의 UITableView와 하는 일이 상당히 비슷합니다.
- 하지만 구현하기는 훨씬 간편하다고 생각합니다.
정적 리스트
- 정적 List에 대한 예시를 보여드리겠습니다.
- 우선 FamilyRow라는 struct가 있습니다.
- 이 struct는 name 변수와 Text를 리턴하는 body를 갖고 있습니다.
- List의 아이템으로 FamilyRow를 넣어주고, 각각의 FamilyRow에 서로 다른 name을 입력해줍니다.
- 그리고 실행해보면, 각 FamilyRow의 텍스트가 리스트 형태로 표시되는 것을 볼 수 있습니다.
struct FamilyRow: View {
var name: String
var body: some View {
Text("Family: \(name)")
}
}
struct ContentView: View {
var body: some View {
List {
FamilyRow(name: "Hohyeon")
FamilyRow(name: "Moon")
FamilyRow(name: "Jigom")
}
}
}
다이나믹 리스트
- Family라는 Identifiable 프로토콜을 상속 받는 struct가 있습니다.
- Identifiable을 상속 받기 위해서는 고유 id 값만 있으면 되는데요.
- Family struct에 id와 name 변수를 선언합니다.
- FamilyRow는 정적 List를 다룰 때와 비슷한데요.
- 다이나믹 리스트를 구성하는 것인만큼 정적인 name 변수 대신 family라는 Family 타입 변수를 선언합니다.
- ContentView에서는 List에 들어갈 first, second, third 아이템을 만듭니다.
- 이를 families 배열에 넣어준 뒤, return 값으로 리스트를 반환합니다.
- families 배열안에 있는 family element를 각각 반복 실행해서 List에 보여줍니다.
struct Family: Identifiable {
var id = UUID()
var name: String
}
struct FamilyRow: View {
var family: Family
var body: some View {
Text("Family: \(family.name)")
}
}
struct ContentView: View {
let first = Family(name: "Hohyeon")
let second = Family(name: "Moon")
let third = Family(name: "Jigom")
var body: some View {
let families = [first, second, third]
return List(families) { family in
FamilyRow(family: family)
}
}
}
List 아이템 선택
- 앞에서와 같이 Family 구조체와 families라는 배열이 있습니다.
- 여기에 binding 가능한 multiSelection Set 타입 변수가 있습니다.
- List에 families와 multiSelection을 넣어주고 네비게이션 바 버튼으로
EditButton
을 넣어봅니다. - 그러면
EditButton
을 눌렀을때 List의 각 row를 선택할수 있게됩니다.
struct ContentView: View {
struct Family: Identifiable {
var id = UUID()
var name: String
}
private var families = [
Family(name: "Hohyeon"),
Family(name: "Moon"),
Family(name: "Jigom")
]
@State private var multiSelection = Set<UUID>()
var body: some View {
NavigationView {
List(families, selection: $multiSelection) {
Text($0.name)
}
.navigationTitle("Family")
.toolbar { EditButton() }
}
}
}
List 아이템 순서 변경
- List의 아이템을 편집하기 위해서는 편집 버튼과 편집 상태에서 작동하는 함수의 정의가 필요한데요.
- 우선, 네비게이션 바 아이템으로 편집 버튼을 만듭니다.
- .onMove(perform: ...)으로 편집 상태에 진입 했을 때 작동할 함수를 부여합니다.
- 그리고 편집 상태에서 실행할 함수를 정의 해줍니다.
struct ContentView : View {
@State var users = ["Hohyeon", "Moon", "Jigom"]
var body: some View {
NavigationView {
List {
ForEach(users, id: \.self) { user in
Text(user)
}
.onMove(perform: move)
}
.navigationBarItems(trailing: EditButton())
}
}
func move(from source: IndexSet, to destination: Int) {
let reversedSource = source.sorted()
for index in reversedSource.reversed() {
users.insert(users.remove(at: index), at: destination)
}
}
}
List 아이템 삭제
- List의 아이템을 삭제하기 위해서는 어려울것 없습니다.
- ForEach로 뿌려진 Text 아이템 뒤에 .onDelete(perform: )을 달아줍니다.
- 그리고 삭제 버튼을 누르면 실행할 함수를 정의 해줍니다.
struct ContentView : View {
@State var users = ["Hohyeon", "Moon", "Jigom"]
var body: some View {
List {
ForEach(users, id: \.self) { user in
Text(user)
}
.onDelete(perform: delete)
}
}
func delete(at offsets: IndexSet) {
if let first = offsets.first {
users.remove(at: first)
}
}
}
List에 섹션 추가
- List에 섹션을 추가하기 위해서는 리스트안에 Section(header: ...){...}을 넣어줍니다.
- 그리고 Section 안에 List 아이템을 넣어줍니다.
struct TaskRow: View {
var body: some View {
Text("Task item")
}
}
struct ContentView : View {
var body: some View {
List {
Section(header: Text("Important")) {
TaskRow()
TaskRow()
TaskRow()
}
Section(header: Text("Other")) {
TaskRow()
TaskRow()
TaskRow()
}
}
}
}
List 스타일링
- List를 스타일링 하기 위해서는 List 뒤에 .listStyle(...)를 달아줍니다.
- listStyle 안에는 ListStyle 타입이 들어가서 예를들어, .grouped가 있습니다.
struct GroupedRow: View {
var body: some View {
Text("Task Row")
}
}
struct ContentView : View {
var body: some View {
List {
Section(header: Text("Grouped")) {
GroupedRow()
GroupedRow()
GroupedRow()
}
}
.listStyle(.grouped)
}
}
마무리
- 이렇게 해서 SwiftUI에서는 List를 어떻게 만드는지에 대해 알아봤습니다.