Core Data에서 데이터를 필터링하기 위해서는 NSFetchRequest에 대해 조금 더 살펴볼 필요가 있다.
Core Data에서 데이터를 검색하는데 사용되는 객체이며, 데이터베이스에서 원하는 엔터티의 레코드를 쿼리하기 위해 필요한 정보를 포함한다.
쉽게 말하면 내가 저장한 데이터를 전체 다 가져올 지, 몇개만 뽑아서 가져올 지, 가져와서 뭘 할 지 오더를 내리는 객체라고 이해하면 된다.
NSFetchRequest를 생성할 때 검색하려고 하는 엔터티를 지정해야 한다.
엔터티를 지정하는 방법은 여러가지가 있는데 코드의 가독성을 고려하여 작성한다.
// (1)
let request = NSFetchRequest<Entity>(entityName: "Entity")
// (2)
let request: NSFetchRequest<Entity> = Entity.fetchRequest()
// (3)
let request = Entity.fetchRequest()
3가지 방법 모두 NSFetchRequest를 생성하는 방법이다.
NSFetchRequest
를 직접 생성하고 엔터티의 이름을 지정하여 검색 요청을 정의entityName
매개변수에는 검색할 엔터티의 이름을 String으로 전달fetchRequest()
메서드를 사용하는 방식NSFetchRequest<Entity>
라는 정확한 타입 정보를 가지고 있음NSPredicate를 사용하여 데이터를 필터링 할 수 있다.
필터링은 연산자, 표현식 등 포맷을 지정하여 구현할 수 있다.
비교 연산자
==, !=, <, >, <=, >= 등의 비교 연산자를 통해 값을 비교한다.
NSPredicate(format: "age == 25") // 일치하는 항목 검색
NSPredicate(format: "name != 'Mike'") // 일치하지 않는 항목 검색
NSPredicate(format: "height > 160") // 큰 항목 검색
논리 연산자
AND, OR, NOT 등의 논리 연산자를 사용하여 여러 조건을 결합한다.
SPredicate(format: "age > 25 AND height > 160")
NSPredicate(format: "name == 'Jenny' OR name == 'Rose'")
NSPredicate(format: "NOT isComplete")
문자열 비교
LIKE, BEGINSWITH, CONTAINS, ENDSWITH 등을 사용하여 문자열을 비교할 수 있다.
// name이 J로 시작하는 항목 검색
NSPredicate(format: "name BEGINSWITH 'J'")
// 대소문자 구분없이 email에 ''이 포함된 항목 검색
NSPredicate(format: "email CONTAINS[c] 'example.com'")
배열 & 집합
IN 연산자를 사용하여 배열 또는 집합에서 값을 검색할 수 있다.
let favoriteColors = ["Red", "Blue", "Green"]
// color가 favoriteColors 배열에 포함된 항목 검색
NSPredicate(format: "color IN %@", favoriteColors) // %@ -> 컴마 뒤에 오는 객체
NULL
nil 값 또는 존재하지 않는 값(NSNull())을 검색할 때 nil, NIL을 사용한다.
NSPredicate(format: "middleName == nil")
NSPredicate(format: "middleName == NIL")
포맷 문자열
%@
: 객체를 나타내며, 문자열, 숫자, 불리언 값을 나타낼 때 사용함%K
: 키 경로를 나타내며, 엔터티의 속성 이름 또는 관계의 키 경로를 사용할 때 유용함%d
, %f
, %@
: 정수, 부동 소수점, 문자열 값을 나타내며, %@는 모든 타입의 값을 받을 수 있음%C
: 문자(char) 값을 나타냄NSSortDescriptor를 사용하여 정렬 기준을 지정할 수 있다.
오름차순
let sortDescriptor = NSSortDescriptor(key: "name", ascending: true)
내림차순
let sortDescriptor = NSSortDescriptor(key: "age", ascending: false)
복합정렬
여러 속성을 조합하여 복합 정렬이 가능하다.
let sortDescriptor1 = NSSortDescriptor(key: "continent", ascending: true)
let sortDescriptor2 = NSSortDescriptor(key: "country", ascending: true)
let compoundSortDescriptor = [sortDescriptor1, sortDescriptor2]
Custom 정렬
비교 함수 또는 클로저를 사용하여 정렬을 커스텀할 수 있다.
예를 들어, 날짜를 기준으로 정렬하되, 특정 날짜 이후의 항목은 먼저 나오도록 할 수 있다.
// 각 날짜를 dateAfter와 비교
let sortDescriptor = NSSortDescriptor(key: "date", ascending: true, comparator: { (date1, date2) -> ComparisonResult in
// date1이 dateAfter보다 큰 경우
if date1.compare(dateAfter) == .orderedDescending {
// date1을 dateAfter 이후로 정렬
return .orderedAscending
// date2가 dateAfter보다 큰 경우
} else if date2.compare(dateAfter) == .orderedDescending {
// date2를 dateAfter 이후로 정렬
return .orderedDescending
} else {
return date1.compare(date2)
}
})
상기 코드는 사용자 정의 비교 로직을 사용하여 날짜를 정렬하며, dateAfter 날짜 이후에 오는 항목들은 앞으로, 이전에 오는 항목들은 뒤로 정렬된다.
Localized 문자열 정렬
문자열을 로케일에 맞게 정렬할 수 있다.
let sortDescriptor = NSSortDescriptor(key: "localizedTitle", ascending: true, selector: #selector(NSString.localizedCaseInsensitiveCompare(_:)))
key: "localizedTitle"
ascending: true
ascending
매개변수는 정렬 순서를 결정(true는 오름차순)selector: #selector(NSString.localizedCaseInsensitiveCompare(_:))
selector
매개변수는 비교자(comparator)를 지정함NSString.localizedCaseInsensitiveCompare(_:)
는 Foundation 프레임워크에 있는 문자열 비교 메서드로, 문자열을 로케일에 따라 비교하고 대소문자를 무시하여 정확한 로케일 및 대소문자 무시 비교를 수행함그럼 이제 지금 만들고 있는 어플에 필터링을 적용해보자!