봄날은 갔다. 이제 그 정신으로 공부하자

3-1. SwiftUI Tutorial - List filter & sort 본문

iOS Tip

3-1. SwiftUI Tutorial - List filter & sort

길재의 그 정신으로 공부하자 2022. 3. 8. 22:22

이 글은 swiftUI Tutorial 중 3번째 항목인 "Handling User Input" 내용을 기반으로 설명합니다.

전체 소스 및 내용이 궁금하신 분은 아래 링크를 참고해주세요.

https://developer.apple.com/tutorials/swiftui/handling-user-input

 

 

이 글은 List에 표시되는 데이터의 필터링 또는 정렬이 필요할 때 사용하는 filter 함수와 sorted 함수에 대해 설명합니다.

 

 

filter

filter 함수는 dictionary에 있는 값 중 원하는 값만 가져올 때 사용하는 함수로 Bool 값을 반환하며 true일 때의 값들이 결과에 포함됩니다.

Landmark 데이터를 예를 들어 설명하면, 데이터 중 isFavorite 값이  true인 데이터만 리스트에 표시하고자 할 때 사용할 수 있습니다.

사용법은 다음과 같습니다.

var filteredLandmarks = landmarks.filter { landmark in
     return (landmark.isFavorite)
}

 

위 내용을 return값을 비롯한 생략 가능한 내용을 생략해 간략화 하면 다음과 같이 사용할 수 있습니다.

var filteredLandmarks = landmarks.filter {
    ($0.isFavorite)
}

 

토글 값에 따라 전체 데이터를 보여주거나 isFavorite 값이  true인 데이터만 보여주고자 할 때 아래와 같이 사용하면 될 것 같지만 에러가 발생합니다.

@State private var showFavoriteOnly = false

var filteredLandmarks = landmarks.filter {
    (! showFavoriteOnly || $0.isFavorite)
}
...

 

에러가 발생하는 이유는 showFavoriteOnly 값이 생성되기 전에 사용되어서인데 이러한 문제를 해결하기 위해서는 landmarks의 filter 값을 받아오는것이 아니라 아래와 같이 새로운 Dictionary 인스턴스를 생성해주어야 합니다.

@State private var showFavoriteOnly = false

var filteredLandmarks: [Landmark] {
    landmarks.filter {
        (!showFavoriteOnly || $0.isFavorite)
    }
}

 

전체 코드는 아래와 같습니다.

import SwiftUI

struct LandmarkList: View {
    @State private var showFavoriteOnly = false

    var filteredLandmarks: [Landmark] {
        landmarks.filter {
            (!showFavoriteOnly || $0.isFavorite)
        }
    }
    
    var sortedLandmarks = landmarks.sorted { (first, second) -> Bool in
        return first.name < second.name
    }
    
    var body: some View {
        NavigationView {
            List {
                Toggle(isOn: $showFavoriteOnly) {
                    Text("Favorites only")
                }

                ForEach(filteredLandmarks) { landmark in
                    NavigationLink {
                        LandmarkDetail(landmark: landmark)
                    } label: {
                        LandmarkRow(landmark: landmark)
                    }
                }
            }
        }
        .navigationTitle("Landmarks")
    }
}

 

sort

sort 함수는 dictionary에 있는 값을 원하는 값을 기준으로 정렬하고자 할 때 사용하는 함수로 두개의 값을 비교한 결과를 Bool 값으로 반환하며 이를 기준으로 정렬한 값들이 결과에 포함됩니다.

Landmark 데이터를 예를 들어 설명하면, 데이터를 이름순으로 정렬해 리스트에 표시하고자 할 때 사용할 수 있습니다.

사용법은 다음과 같습니다.

var sortedLandmarks = landmarks.sorted { (first, second) -> Bool in
    return first.name < second.name
}

 

위 내용을 return값을 비롯한 생략 가능한 내용을 생략해 간략화 하면 다음과 같이 사용할 수 있습니다.

var sortedLandmarks = landmarks.sorted { 
    $0 < $1.name
}

 

sort를 추가해 이름순으로 정렬한 데이터를 필터링하고자 한다면 아래와 같이 사용해주면 됩니다.

var sortedLandmarks = landmarks.sorted { (first, second) -> Bool in
    return first.name < second.name
}
    
var filteredLandmarks: [Landmark] {
    sortedLandmarks.filter {
        (!showFavoriteOnly || $0.isFavorite)
    }
}

 

정리

Dictionary 데이터 중 원하는 값만 필터링하고자 할 때는 filter 함수를 정렬이 필요할 때는 sort 함수를 사용해주면 됩니다.

 

Comments