NSPredicate?
Fetch 작업이나, in-memory filtering 작업을 할 때, 검색에 대한 제약 사항을 논리적인 조건들(Logical conditions)로 정의할 수 있는 class입니다.
그 중 대표적인 용도가 CoreData의 NSFetchRequest를 할 때, NSPredicate의 조건에 충족하는 객체들만을 필터링하여 받아올 수 있습니다.
NSFetchRequest의 predicate 프로퍼티
그래서 NSFetchRequest의 공식 문서에 가보면, predicate라는 프로퍼티가 있는것을 확인할 수 있습니다.
The predicate instance constrains the selection of objects the NSFetchRequest instance is to fetch.
NSFetchRequest 인스턴스가 fetch할 때 선택할 객체들에 대한 제약사항을 명시해주는 역할을 한다고 나와있습니다.
Predicate Format String Syntax
그럼 이 NSPredicate는 어떤 형태로 제약사항을 주는지 직접 코드로 작성하며 알아보도록 하겠습니다.
@objcMembers class Volunteer: NSObject {
let name: String
let age: Int
let score: Double
init(name: String, age: Int, score: Double) {
self.name = name
self.age = age
self.score = score
}
}
let kim = Volunteer(name: "Kim", age: 27, score: 90.5)
let park = Volunteer(name: "Park", age: 25, score: 85.3)
let james = Volunteer(name: "James", age: 30, score: 97.8)
let lee = Volunteer(name: "Lee", age: 31, score: 78.9)
let volunteers = [kim, park, james, lee] as NSArray
NSObject를 상속받는 Volunteer라는 클래스를 만들고, 인스턴스 4개를 만들어 volunteers라는 NSArray를 생성해주었습니다.
이제 NSArray의 filtered 메서드를 활용하여 NSPredicate 를 만들어 volunteers 내부의 값을 필터링 해보겠습니다.
dump(volunteers.filtered(using: NSPredicate(
format: "name = 'Kim'")
))
우선 첫번째 format은 "name = 'Kim'" 입니다. name이 Kim인 것만 필터링 하는 것이고, = 또는 == 을 사용할 수 있습니다.
dump(volunteers.filtered(using: NSPredicate(
format: "age < 30")
))
다음은 "age < 30" 즉, age가 30미만인 값들만 가져오는 format입니다.
dump(volunteers.filtered(using: NSPredicate(
format: "score BETWEEN {90, 100}")
))
이번에는 "score BETWEEN {90, 100}" 입니다. score의 값이 90~100 사이인 값들을 가져올 수 있습니다. 사용하다보니 이런 방식이 SQL과 정말 비슷하다는 생각이 듭니다.
%@ and %K
format에 %@와 %K를 잘 활용하여 사용할 수 있는데, %@와 %K에 대해서 알아보겠습니다.
- %@ : 변수 argument로, 주로 string, number, date와 같은 object 값으로 대체할 수 있습니다.
- %K : 변수 argument로 keypath와 대체할 수 있습니다.
C언어의 printf(%d, 100); 할때 %d 와 비슷한 역할인것 같습니다.
dump(volunteers.filtered(using: NSPredicate(
format: "%K = %@",
"name", "Kim")
))
이런식으로 사용하여, name이 Kim인 것을 찾아낼 수 있고,
dump(volunteers.filtered(using: NSPredicate(
format: "%K CONTAINS %@",
"name", "K")
))
CONTAINS를 활용하여 name에 K가 들어가는 것도 찾아낼 수 있습니다.
또한 실제 Raywenderlich.com의 CoreData를 공부하는 중에
let request: NSFetchRequest<BowTie> = BowTie.fetchRequest()
request.predicate = NSPredicate(
format: "%K = %@",
argumentArray: [#keyPath(BowTie.searchKey), selectedValue]
)
BowTie의 searchKey와 selectedValue가 같은 값에 대한 fetch를 진행하기 위해 NSPredicate를 사용할 수 있었습니다.
참고
- 더 많은 Operator들을 확인할 수 있고, 더 자세한 정보들이 위 공식문서에 있습니다!
https://developer.apple.com/documentation/foundation/nspredicate
'CoreData' 카테고리의 다른 글
[Core Data] Delete Rule을 이해하고 적절하게 사용해보자! (0) | 2023.01.26 |
---|---|
CoreData ) Core Data stack에 대해서 (0) | 2022.05.06 |
CoreData ) NSSecureCoding (정말정말정말 간단하게 알아봄) (0) | 2022.05.04 |
CoreData ) .xcdatamodeld? (0) | 2022.04.26 |