SwiftUI 리스트와 내비게이션
List 뷰 :
- 수직 방향의 목록 형태로 사용자에게 정보를 제공하는 방법을 제공
- 리스트 항목은 사용자가 터치했을 때 앱의 다른 영역으로 이동 ( 내비게이션 )
- 정적 데이터와 동적 데이터 모두를 표현가능
- 추가, 삭제, 항목 순서 재정렬 작업가능
SwiftUI 리스트
UIKit의 TableView 클래스와 비슷한 기능
struct ContentView: View {
var body: some View {
Text("Wash the car")
Text("Vacuum house")
Text("Pick up kids from school bus @ 3pm")
Text("Auction the kids on eBay")
Text("Order Pizza for dinner")
}
}
여러 컴포넌트를 조합해서 셀에 표시
List {
HStack {
Image(systemName: "trash.circle.fill")
Text("Take out the trash")
}
HStack {
Image(systemName: "person.2.fill")
Text("Pick up the kids")
}
HStack {
Image(systemName: "car.fill")
Text("Wash the car")
}
}
SwiftUI 동적 리스트
동적: 변할 수 있는 항목들(추가, 편집, 삭제)
표시될 데이터는 Identifiable 프로토콜 을 따르는 클래스 또는 구조체 내에 포함
-> Identifiable 프로토콜을 사용하려면, id 프로퍼티 가 객체에 존재
(리스트에서 각 항목을 고유하게 식별하는데 사용)
- 표준 스위프트 타입
- Hashable 프로토콜을 따르는 모든 스위프트 타입(String, Int, UUID..)
- 커스텀 타입
struct ToDoItem : Identifiable {
var id = UUID()
var task: String
var imageName: String
}
배열을 이용한 리스트 데이터 제공
var listData: [ToDoItem] = [
ToDoItem(task: "Take out trash", imageName: "trash.circle.fill"),
ToDoItem(task: "Pick up the kids", imageName: "person.2.fill"),
ToDoItem(task: "Wash the car", imageName: "car.fill")
]
struct ContentView: View {
var body: some View {
List(listData) { item in
HStack {
Image(systemName: item.imageName)
Text(item.task)
}
}
}
}
반복문을 실행하여 HStack 선언부를 재사용
동적 데이터와 정적 데이터를 함께 표현하는 경우: ForEach 구문 사용
struct ContentView: View {
@State var toggleStatus = true
var body: some View {
List {
Toggle(isOn: $toggleStatus) { // 정적 데이터
Text("Allow Notifications")
}
ForEach (listData) { item in // 동적 데이터
HStack {
Image(systemName: item.imageName)
Text(item.task)
}
}
}
}
}
Section 구현
List {
Section(header: Text("Settings")) {
Toggle(isOn: $toggleStatus) {
Text("Allow Notifications")
}
}
Section(header: Text("To Do Tasks")) {
ForEach (listData) { item in
HStack {
Image(systemName: item.imageName)
Text(item.task)
}
}
}
}
NavigationView와 NavigationLink
리스트의 항목을 터치하여 다른 화면으로 이동
- 리스트를 NavigationView 안에 넣는다.
- 리스트의 각 행을 NavigaionLink 컨트롤로 감싼다.
var body: some View {
NavigationView {
List {
Section(header: Text("Settings")) {
Toggle(isOn: $toggleStatus) {
Text("Allow Notifications")
}
}
Section(header: Text("To Do Tasks")) {
ForEach (listData) { item in
HStack {
NavigationLink(destination: Text(item.task)) {
Image(systemName: item.imageName)
Text(item.task)
}
}
}
}
}
}
}
Navigaiton 타이틀 바 설정, 버튼 추가
NavigationView {
List {
.
.
}
.navigationBarTitle(Text("To Do List"))
.navigationBarItems(trailing: Button(action: addTask) {
Text("Add")
})
}
편집 가능하게 만들기
- onDelete() 수정자: 데이터 소스에서 해당 항목을 삭제
ForEach (listData) { item in HStack { NavigationLink(destination: Text(item.task)) { Image(systemName: item.imageName) Text(item.task) } } } .onDelete(perform: deleteItem)
func deleteItem(:IndexSet)
- 각 셀이 삭제될 때 호출되는 함수
- 삭제될 셀의 오프셋(offset)을 가진 IndexSet 객체 가 전달
- 반드시 IndexSet을 매개변수로 받는다
func deleteItem(at offsets: IndexSet) { // 데이터 소스에서 항목을 삭제하는 코드 }
- onMove() 수정자: 데이터 소스에서 항목의 순서를 변경
- 이동할 행의 현재 위치를 담고 있는 IndexSet 객체 와 이동하게 될 곳을 가리키는 정수 가 전달
- EditButton 인스턴스: 버튼을 터치하면 자동으로 편집가능한 상태로 전환
List { . . ForEach (listData) { item in HStack { NavigationLink(destination: Text(item.task)) { Image(systemName: item.imageName) Text(item.task) } } } .onDelete(perform: deleteItem) .onMove(perform: moveItem) . . } .navigationBarTitle(Text("To Do List")) .navigationBarItems(trailing: Button(action: addTask) { Text("Add") }) .navigationBarItems(trailing: EditButton())
func moveItem(from source: IndexSet, to destination: Int) { // 항목을 재배열하는 코드 }