swiftUI 기반 환경에서 CoreData를 사용시 데이터를 필터하여 보여주어야 할 때가 있다. 차근차근 알아보자
데이터 불러오기
먼저 FoodEntity라는 데이터를 사용한다고 가정해보자. 다음과 같이 CoreData로 부터 데이터를 불러올 것이다.
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \FoodEntity.timestamp, ascending: true)],
animation: .default
)
private var foods: FetchedResults<FoodEntity>
필터 적용하기
여기에 predicate인자를 통해 필터를 적용할수 있다
@State var filterKey = "한식"
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \FoodEntity.timestamp, ascending: true)],
predicate: NSPredicate(format: "category == %s", filterKey)
animation: .default
)
하지만 이렇게되면 컴파일 에러가 발생한다. 왜냐하면, @FetchRequest는 var filterKey 보다 먼저 실행되기 때문이다. 즉, 변수를 활용해서 dynamic 하게 데이터에 필터를 적용할 수 없다는 뜻이다.
NSPredicate 관련 문법은 다음을 참고하자
Predicate Programming Guide
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Predicates/AdditionalChapters/Introduction.html#//apple_ref/doc/uid/TP40001789
Introduction
Introduction Predicates provide a general means of specifying queries in Cocoa. The predicate system is capable of handling a large number of domains, including Core Data and Spotlight. This document describes predicates in general, their use, their syntax
developer.apple.com
맘에 안드는 해결방법
아래 링크된 대로 FilteredList를 사용하며, View를 새로 init 하는 방법이 있는데 코드량만 늘어나고 가독성만 나빠질뿐, swiftui 스럽지 않다고 생각했다.
https://www.hackingwithswift.com/books/ios-swiftui/dynamically-filtering-fetchrequest-with-swiftui
Dynamically filtering @FetchRequest with SwiftUI - a free Hacking with iOS: SwiftUI Edition tutorial
Was this page useful? Let us know! 1 2 3 4 5
www.hackingwithswift.com
진짜 해결방법
다음과 같이 필터를 wrapping 하는 struct를 만들어주자
struct FilterScope: Equatable {
var filter: String?
var predicate: NSPredicate? {
guard let filter = filter else { return nil }
return NSPredicate(format: "category == %@", filter)
}
}
인스턴스화 해주고
@State private var filterScope: FilterScope = FilterScope(filter: nil)
아래와 같이 onChange 콜백을 걸어준다. 앞으로 filter가 변경될때 마다 감지되어 자동으로 FetchedResults에 필터를 적용시켜줄 것이다.
NavigationView {
// some view..
}.onChange(of: filterScope) { newValue in
foods.nsPredicate = filterScope.predicate
}
swiftui 스럽죠? 주의할점은 struct에 Equatable을 붙여주는것을 잊지말자
'iOS' 카테고리의 다른 글
SwiftUI Navigation View To Root - 네비게이션 뷰 관리하기 (0) | 2021.12.04 |
---|