Starbucks Caramel Frappuccino
본문 바로가기
  • 그래 그렇게 조금씩
SwiftUI/SwiftUI(Basic)

29. [SwiftUI] List() 리스트뷰

by Toughie 2023. 4. 27.

VStack과 비슷?하지만 손쉽게 데이터 추가/삭제/정렬이 가능한 리스트에 대해 알아보자.

리스트를 활용하면 아래와 같은 설정 화면도 구현할 수 있다.(우측은 이번 예시)

코드로 살펴보자

//  Created by Toughie on 2023/04/27.
//

import SwiftUI

struct ListPrac: View {
    
    //리스트의 요소를 위한 더미 데이터 배열
    
    @State var fruits: [String] = [ "apple", "orange", "banana", "waterMellon" ]
    @State var veggies: [String] = [ "tomato", "carrot", "sweetPotato" ]
    
    var body: some View {
    //네비게이션뷰 안에 리스트 
        NavigationView {
        
            List {
            //섹션
                Section {
                //ForeEach 활용
                    ForEach(fruits, id: \.self) { fruit in
                        Text(fruit.capitalized)
                            .foregroundColor(Color.white)
                            .padding(.vertical)
                        // 내부 요소 크기 직접 설정(꽉 채우고 싶을 때)
                        // .frame(maxWidth: .infinity, maxHeight: .infinity)
                        // .background(Color.orange)
                    }
                    
                    // .onDelete 메서드 
                    // .onDelete { indexSet in delete(indexSet: indexSet)}
                    // 축약(아래에 따로 정리)
                    .onDelete(perform: delete)
                    
                    .onMove(perform: move)
                    //리스트의 행 배경을 바꿈
                    .listRowBackground(Color.cyan)
                }
                //섹션 헤더
            header: {
                HStack {
                    Text("Fruits")
                    Image(systemName: "basket.fill")
                }
                .font(.headline)
                .foregroundColor(Color.blue)
            }
                
                Section {
                    ForEach(veggies, id: \.self) { veggies in
                        Text(veggies.capitalized)
                    }
                } header: {
                    Text("veggies")
                }
                
            }
            .accentColor(.green)
            //리스트 스타일(본 예시는 Inset)
//            .listStyle(GroupedListStyle())
//            .listStyle(InsetGroupedListStyle())

//네비게이션바 설정(타이틀, 아이템)
            .navigationTitle("Mart")
            .navigationBarItems(
                leading: EditButton(),
                trailing: addButton
            )
        }
        .accentColor(.gray)
    }
    //add버튼
    var addButton: some View {
        Button("Add", action: {
            add()
        })
    }
    
    
    // 함수 추출 정리
    func delete(indexSet: IndexSet) {
        fruits.remove(atOffsets: indexSet)
    }
    
    func move(from: IndexSet, to: Int) {
        fruits.move(fromOffsets: from, toOffset: to)
    }
    
    func add() {
        fruits.append("Mango")
    }
    
}

 

onDelete 메서드는 (IndexSet) -> Void 형식의 클로저가 필요하다.

배열에서 요소를 삭제하는 delete 함수를 살펴보면

    func delete(indexSet: IndexSet) {
        fruits.remove(atOffsets: indexSet)
    }

(IndexSet) -> Void 형식과 일치한다.

그래서 delete 함수 자체를 직접 전달하면 함수의 형식과 일치하는 클로저가 자동으로 생성되어 사용된다.

-> 더 간결하고 가독성 좋은 코드를 작성할 수 있다.

 

IndexSet

List 뷰 내에서 유저가 선택한 행을 추적하기 위해 selection 매개변수를 사용 가능하다.

또한 사용자가 행을 삭제하거나 이동할 때 (onDelete, onMove) 선택된 항목의 인덱스(인덱스 집합)가 매개변수로 필요하다.

IndexSet은 '정수 값의 집합' 이다.

사용자가 선택한 행의 인덱스를 저장하는 데이터 타입!

만약 1번 3번 행을 선택하면 IndexSet은 {0, 2}가 된다.