Chris.Koo
Developer 쿠의 개발이야기
Chris.Koo
전체 방문자
오늘
어제
  • 분류 전체보기 (17)
    • Python (2)
    • Android (5)
    • iOS (2)
    • 알고리즘 (0)
    • Git (1)
    • 생각 (1)
    • Web (4)
    • Blockchain (1)
    • 자동차 (1)

블로그 메뉴

  • 홈
  • 태그
  • 미디어로그
  • 위치로그
  • 방명록

공지사항

인기 글

태그

  • appversion
  • imap_unordered
  • BaseActivity
  • DynamicList
  • rxjava
  • Blockchain
  • rxbus
  • multiprocessing
  • basefragment
  • RemoteConfig
  • kaikas
  • rxKotlin
  • Klay
  • viewtoroot
  • SSR
  • ios
  • firebase
  • Kotlin
  • react
  • isdetaillink
  • swiftUI
  • feedelegation
  • Android
  • Python
  • NavigationLink
  • fetchedresults
  • Klaytn
  • viewBinding
  • rootView
  • nextjs

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
Chris.Koo

Developer 쿠의 개발이야기

iOS

SwiftUI + CoreData FetchRequest Predicate 사용법

2021. 12. 4. 02:51

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
    'iOS' 카테고리의 다른 글
    • SwiftUI Navigation View To Root - 네비게이션 뷰 관리하기
    Chris.Koo
    Chris.Koo
    개발하며 얻은 지식과 방법론 및 일화에 대해 남기고자 만든 블로그 입니다

    티스토리툴바