SwiftUI

SwiftUI - 리스트와 내비게이션

iosos 2024. 2. 21. 17:46

리스트

  • UIKit의 TableView 클래스와 비슷한 기능
  • 셀에 포함된 하나 이상의 뷰의 각 행을 수직 방향의 목록으로 정보 표현
  • List 구현체
var body: some View {
        List{
            Text("Wash the car")
            Text("Vacuum house")
            Text("Pick up kids from school bus @ 3pm")
            Text("Aucion the kids on eBay")
            Text("Order pizza for dinner")
        }
    }

 

 

 

 

  • 여러 컴포넌트를 조합해서 셀에 표시 가능
  • 리스트의 각 행을 HStack 안의 이미지와 텍스트 컴포넌트 조합으로 구성
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")
            }
        }

 

 

 

 

 

동적 리스트

  • 시간이 지남에 따라 변할 수 있는 항목을 포함하는 리스트라면 동적 리스트로 간주
  • 항목이 추가, 편집, 삭제 될 수 있고, 이러한 변화를 동적으로 반영하도록 리스트 업데이트
  • 표시될 데이터는 Identifiable 프로토콜을 따르는 클래스 또는 구조체 내에 포함되어야 함
  • Identifiable 프로토콜을 사용하려면 리스트에 각 항목을 고유하게 식별하는 id라는 이름의 프로퍼티 객체를 가져야 함
  • id 프로퍼티는 모든 타입, 커스텀 타입이 가능함
    • UUID를 사용하면 각 항목마다 고유한 ID를 자동으로 생성 후 사용 가능 함
  • Identifiable 프로토콜을 따르는 구조체
struct ToDoItem : Identifiable {
    var id = UUID()
    var task : String
    var imageName : String
}

 

 

 

 

 

 

  • ToDoItem 객체들의 배열을 사용하여 리스트에 데이터가 제공되는 것을 구현한 코드
.
.
.

var listData : [ToDoItem] = [
        ToDoItem(task : "Take out the trash", imageName : "trash.circle.fill"),
        ToDoItem(task : "Pick up the kids", imageName : "person.2.fill"),
        ToDoItem(task : "Wash the car", imageName : "car.fill")
    ]

struct Chap25: View {
    var body: some View {
        **List(listData){ item in**
            HStack{
                Image(systemName: item.imageName)
                Text(item.task)
            }
        }
    }
}

→ 반복문을 통해 HStack 선언부를 재사용

 

 

 

 

 

 

  • 정적 데이터와 동적 데이터를 함께 표현하는 경우. ForEach 구문을 이용하여 리스트 body에서 동적 데이터에 대한 반복문을 돌리면서 정적 항목 선언 가능
  • 정적 항목인 토글 버튼과 동적 데이터에 대한 ForEach 구문 사용
struct Chap25: View {
    
    var listData : [ToDoItem] = [
        ToDoItem(task : "Take out the trash", imageName : "trash.circle.fill"),
        ToDoItem(task : "Pick up the kids", imageName : "person.2.fill"),
        ToDoItem(task : "Wash the car", imageName : "car.fill")
    ]
    
    @State var toggleStatus = true
    
    var body: some View {
        List {
            Toggle(isOn : $toggleStatus){
                Text("Allow Notification")
            }
            
            ForEach(listData){ item in
                HStack{
                    Image(systemName: item.imageName)
                    Text(item.task)
                }
            }
        }
    }
}

 

 

 

 

 

  • Section 뷰를 이용하여 헤더와 푸터가 있는 섹션으로 구분
List {
            **Section(header : Text("Setting")){**
                Toggle(isOn : $toggleStatus){
                    Text("Allow Notification")
                }
            }
           
            **Section(header : Text("To Do Tasks")){**
                ForEach(listData){ item in
                    HStack{
                        Image(systemName: item.imageName)
                        Text(item.task)
                    }
                }
            }
        }

 

 

 

 

 

 

NavigationView와 NavigationLink

  • 리스트의 항목을 터치하면 앱의 다른 화면으로 이동하는 것을 구현
  • 리스트를 NavigationView 안에 넣어야 화면이 이동 가능함
  • 리스트의 각 행을 NavigationLink 컨트롤로 감싸면 터치 후 대상 뷰로 이동되도록 구성
  • 제목을 설정하기 위해서 리스트 컴포넌트의 수정자를 사용하여 NavigationView 타이틀 바를 설정 가능
  • 부가적인 작업을 수행하는 버튼도 추가 가능함
  • 네비게이션 타이틀을 ‘To Do List’로 하고, addTask()라는 이름의 메서드를 호출하는 아이템으로 Add 버튼 추가
NavigationView {
   		List {
            .
						.
						.
	     }
        .navigationTitle(Text("To Do List"))
        .navigationBarItems(trailing: Button(action: addTask)){
            Text("Add")
        }
.
.
}

 

 

 

 

 

  • 네비게이션 링크는 할 일에 대한 제목 표시하는 Text 뷰를 가진 새로운 화면 표시
  • 각 행에는 할 일에 대한 제목과 갈매기 모양(chevron)이 나타남
  • 항목을 터치하면 Text 뷰로 이동
var body: some View {
        NavigationView{
            List {
                Section(header : Text("Setting")){
                    Toggle(isOn : $toggleStatus){
                        Text("Allow Notification")
                    }
                }
               
                Section(header : Text("To Do Tasks")){
                    ForEach(listData){ item in
                        HStack{
                            NavigationLink(destination: Text(item.task)){
                                Image(systemName: item.imageName)
                                Text(item.task)
                            }
                        }
                    }
                }
            }
            .navigationTitle(Text("To Do List"))
        }
    }

 

 

 

 

편집 기능 구현

항목 삭제

  • onDelete() 수정자를 각각의 리스트 셀에 추가하면 데이터 소스에서 해당 항목을 삭제 가능하게 할 수 있음
  • 이 메서드가 호출되면 삭제될 행의 오프셋(offset)을 가진 IndexSet 객체가 전달됨
  • 이 메서드를 구현하면 행을 왼쪽으로 스와이프 할 때 Delete 버튼이 생김
  • func deleteItem(:IndexSet) 함수는 각 셀이 삭제될 때 호출되는 함수 → IndexSet을 매개변수로 받음
NavigationView{
            List {
                Section(header : Text("Setting")){
                    Toggle(isOn : $toggleStatus){
                        Text("Allow Notification")
                    }
                }
               
                Section(header : Text("To Do Tasks")){
                    ForEach(listData){ item in
                        HStack{
                            NavigationLink(destination: Text(item.task)){
                                Image(systemName: item.imageName)
                                Text(item.task)
                            }
                        }
                    }
                    .onDelete(perform: deleteItem)
                }
            }
            .navigationTitle(Text("To Do List"))
        }
        
        func deleteItem(at offsets: IndexSet){
            // 데이터 소스에서 항목을 삭제하는 코드
        }
...
}

 

 

 

 

 

 

항목 이동

  • onMove() 수정자는 항목을 이동하여 순서를 변경하기 위해 사용됨
  • 이 메서드는 이동할 행의 현재 위치를 담고 있는 IndexSet 객체와 이동하게 될 곳을 가리키는 정수가 전달됨
  • 버튼을 추가하여, 버튼을 터치하면 자동으로 리스트는 편집 가능한 생태로 전환되며, 사용자는 항목을 이동하거나 삭제할 수 있는도록 EditButton 인스턴스를 추가해야 함
  • 편집 버튼은 네비게이션 바 아이템으로 navigationBarItem() 수정자를 이용하여 추가 가능함
NavigationView{
            List {
                Section(header : Text("Setting")){
                    Toggle(isOn : $toggleStatus){
                        Text("Allow Notification")
                    }
                }
               
                Section(header : Text("To Do Tasks")){
                    ForEach(listData){ item in
                        HStack{
                            NavigationLink(destination: Text(item.task)){
                                Image(systemName: item.imageName)
                                Text(item.task)
                            }
                        }
                    }
                    .onDelete(perform: deleteItem)
                    .onMove(perform : moveItem)
                }
            }
            .navigationTitle(Text("To Do List"))
            .navigationBarItems(trailing: EditButton())
        }
        
        func deleteItem(at offsets: IndexSet){
            // 데이터 소스에서 항목을 삭제하는 코드
        }
        
        func moveItem(from source : IndexSet, to destination : Int){
            // 항목을 재배열 하는 코드
        }