fetchRequest.sortDescriptors = [NSSortDescriptor(key: “id”, ascending: true, selector: “localizedStandardCompare:” )]
fetchRequest.sortDescriptors = [NSSortDescriptor(key: “id”, ascending: true, selector: “localizedStandardCompare:” )]
original source: https://nshipster.com/nspredicate/
core data의 query(predicate) 작업의 기본
my review point is 9/10
NSPredicate
is a Foundation class that specifies how data should be fetched or filtered. Its query language, which is like a cross between a SQL WHERE
clause and a regular expression, provides an expressive, natural language interface to define logical conditions on which a collection is searched.
It’s easier to show NSPredicate
in use, rather than talk about it in the abstract, so we’re going to revisit the example data set used in the NSSortDescriptor
article:

class Person: NSObject {
let firstName: String
let lastName: String
let age: Int
init(firstName: String, lastName: String, age: Int) {
self.firstName = firstName
self.lastName = lastName
self.age = age
}
override var description: String {
return "(firstName) (lastName)"
}
}
let alice = Person(firstName: "Alice", lastName: "Smith", age: 24)
let bob = Person(firstName: "Bob", lastName: "Jones", age: 27)
let charlie = Person(firstName: "Charlie", lastName: "Smith", age: 33)
let quentin = Person(firstName: "Quentin", lastName: "Alberts", age: 31)
let people = [alice, bob, charlie, quentin]
let bobPredicate = NSPredicate(format: "firstName = 'Bob'")
let smithPredicate = NSPredicate(format: "lastName = %@", "Smith")
let thirtiesPredicate = NSPredicate(format: "age >= 30")
(people as NSArray).filteredArrayUsingPredicate(bobPredicate)
// ["Bob Jones"]
(people as NSArray).filteredArrayUsingPredicate(smithPredicate)
// ["Alice Smith", "Charlie Smith"]
(people as NSArray).filteredArrayUsingPredicate(thirtiesPredicate)
// ["Charlie Smith", "Quentin Alberts"]
Using NSPredicate
with Collections
Foundation provides methods to filter NSArray
/ NSMutableArray
& NSSet
/ NSMutableSet
with predicates.
Immutable collections, NSArray
& NSSet
, have the methods filteredArrayUsingPredicate:
and filteredSetUsingPredicate:
which return an immutable collection by evaluating a predicate on the receiver.
Mutable collections, NSMutableArray
& NSMutableSet
have the method filterUsingPredicate:
, which removes any objects that evaluate to FALSE
when running the predicate on the receiver.
NSDictionary
can use predicates by filtering its keys or values (both NSArray
objects). NSOrderedSet
can either create new ordered sets from a filtered NSArray
or NSSet
, or alternatively, NSMutableSet
can simply removeObjectsInArray:
, passing objects filtered with the negated predicate.
Using NSPredicate
with Core Data
NSFetchRequest
has a predicate
property, which specifies the logical conditions under which managed objects should be retrieved. The same rules apply, except that predicates are evaluated by the persistent store coordinator within a managed object context, rather than collections being filtered in-memory.
Predicate Syntax
Substitutions
%@
is a var arg substitution for an object value—often a string, number, or date.%K
is a var arg substitution for a key path.
let ageIs33Predicate = NSPredicate(format: "%K = %@", "age", "33")
(people as NSArray).filteredArrayUsingPredicate(ageIs33Predicate)
// ["Charlie Smith"]
$VARIABLE_NAME
is a value that can be substituted withNSPredicate -predicateWithSubstitutionVariables:
.
let namesBeginningWithLetterPredicate = NSPredicate(format: "(firstName BEGINSWITH[cd] $letter) OR (lastName BEGINSWITH[cd] $letter)")
(people as NSArray).filteredArrayUsingPredicate(namesBeginningWithLetterPredicate.predicateWithSubstitutionVariables(["letter": "A"]))
// ["Alice Smith", "Quentin Alberts"]
Basic Comparisons
=
,==
: The left-hand expression is equal to the right-hand expression.>=
,=>
: The left-hand expression is greater than or equal to the right-hand expression.<=
,=<
: The left-hand expression is less than or equal to the right-hand expression.>
: The left-hand expression is greater than the right-hand expression.<
: The left-hand expression is less than the right-hand expression.!=
,<>
: The left-hand expression is not equal to the right-hand expression.BETWEEN
: The left-hand expression is between, or equal to either of, the values specified in the right-hand side. The right-hand side is a two value array (an array is required to specify order) giving upper and lower bounds. For example,1 BETWEEN { 0 , 33 }
, or$INPUT BETWEEN { $LOWER, $UPPER }
.
Basic Compound Predicates
AND
,&&
: LogicalAND
.OR
,||
: LogicalOR
.NOT
,!
: LogicalNOT
.
String Comparisons
String comparisons are by default case and diacritic sensitive. You can modify an operator using the key characters c and d within square braces to specify case and diacritic insensitivity respectively, for example firstName BEGINSWITH[cd] $FIRST_NAME.
BEGINSWITH
: The left-hand expression begins with the right-hand expression.CONTAINS
: The left-hand expression contains the right-hand expression.ENDSWITH
: The left-hand expression ends with the right-hand expression.LIKE
: The left hand expression equals the right-hand expression:?
and*
are allowed as wildcard characters, where?
matches 1 character and*
matches 0 or more characters.MATCHES
: The left hand expression equals the right hand expression using a regex-style comparison according to ICU v3 (for more details see the ICU User Guide for Regular Expressions).
Aggregate OperationsRelational Operations
ANY
,SOME
: Specifies any of the elements in the following expression. For example,ANY children.age < 18
.ALL
: Specifies all of the elements in the following expression. For example,ALL children.age < 18
.NONE
: Specifies none of the elements in the following expression. For example,NONE children.age < 18
. This is logically equivalent toNOT (ANY ...)
.IN
: Equivalent to an SQLIN
operation, the left-hand side must appear in the collection specified by the right-hand side. For example,name IN { 'Ben', 'Melissa', 'Nick' }
.
Array Operations
array[index]
: Specifies the element at the specified index inarray
.array[FIRST]
: Specifies the first element inarray
.array[LAST]
: Specifies the last element inarray
.array[SIZE]
: Specifies the size ofarray
.
Boolean Value Predicates
TRUEPREDICATE
: A predicate that always evaluates toTRUE
.FALSEPREDICATE
: A predicate that always evaluates toFALSE
.
NSCompoundPredicate
We saw that AND
& OR
can be used in predicate format strings to create compound predicates. However, the same can be accomplished using an NSCompoundPredicate
.
For example, the following predicates are equivalent:
NSCompoundPredicate(type: .AndPredicateType, subpredicates: [NSPredicate(format: "age > 25"), NSPredicate(format: "firstName = %@", "Quentin")])
NSPredicate(format: "(age > 25) AND (firstName = %@)", "Quentin")
While the syntax string literal is certainly easier to type, there are occasions where you may need to combine existing predicates. In these cases, NSCompoundPredicate -andPredicateWithSubpredicates:
& -orPredicateWithSubpredicates:
is the way to go.
NSComparisonPredicate
Similarly, if after reading last week’s article you now find yourself with more NSExpression
objects than you know what to do with, NSComparisonPredicate
can help you out.
Like NSCompoundPredicate
, NSComparisonPredicate
constructs an NSPredicate
from subcomponents—in this case, NSExpression
s on the left and right hand sides. Analyzing its class constructor provides a glimpse into the way NSPredicate
format strings are parsed:
+ (NSPredicate *)predicateWithLeftExpression:(NSExpression *)lhs
rightExpression:(NSExpression *)rhs
modifier:(NSComparisonPredicateModifier)modifier
type:(NSPredicateOperatorType)type
options:(NSUInteger)options
Parameters
lhs
: The left hand expression.rhs
: The right hand expression.modifier
: The modifier to apply. (ANY
orALL
)type
: The predicate operator type.options
: The options to apply. For no options, pass0
.
NSComparisonPredicate
Types
public enum NSPredicateOperatorType : UInt {
case LessThanPredicateOperatorType
case LessThanOrEqualToPredicateOperatorType
case GreaterThanPredicateOperatorType
case GreaterThanOrEqualToPredicateOperatorType
case EqualToPredicateOperatorType
case NotEqualToPredicateOperatorType
case MatchesPredicateOperatorType
case LikePredicateOperatorType
case BeginsWithPredicateOperatorType
case EndsWithPredicateOperatorType
case InPredicateOperatorType
case CustomSelectorPredicateOperatorType
case ContainsPredicateOperatorType
case BetweenPredicateOperatorType
}
NSComparisonPredicate
Options
NSCaseInsensitivePredicateOption
: A case-insensitive predicate. You represent this option in a predicate format string using a [c] following a string operation (for example, “NeXT” like[c] “next”).NSDiacriticInsensitivePredicateOption
: A diacritic-insensitive predicate. You represent this option in a predicate format string using a [d] following a string operation (for example, “naïve” like[d] “naive”).NSNormalizedPredicateOption
: Indicates that the strings to be compared have been preprocessed. This option supersedes NSCaseInsensitivePredicateOption and NSDiacriticInsensitivePredicateOption, and is intended as a performance optimization option. You represent this option in a predicate format string using a [n] following a string operation (for example, “WXYZlan” matches[n] “.lan”).NSLocaleSensitivePredicateOption
: Indicates that strings to be compared using<
,<=
,=
,=>
,>
should be handled in a locale-aware fashion. You represent this option in a predicate format string using a[l]
following one of the<
,<=
,=
,=>
,>
operators (for example, “straße” >[l] “strasse”).
Block Predicates
Finally, if you just can’t be bothered to learn the NSPredicate
format syntax, you can go through the motions with NSPredicate +predicateWithBlock:
.
let shortNamePredicate = NSPredicate { (evaluatedObject, _) in
return (evaluatedObject as! Person).firstName.utf16.count <= 5
}
(people as NSArray).filteredArrayUsingPredicate(shortNamePredicate)
// ["Alice Smith", "Bob Jones"]
…Alright, that whole dig on predicateWithBlock:
as being the lazy way out wasn’t entirely charitable.
Actually, since blocks can encapsulate any kind of calculation, there is a whole class of queries that can’t be expressed with the NSPredicate
format string (such as evaluating against values dynamically calculated at run-time). And while its possible to accomplish the same using an NSExpression
with a custom selector, blocks provide a convenient interface to get the job done.
One important note: NSPredicate
s created with predicateWithBlock:
cannot be used for Core Data fetch requests backed by a SQLite
store.
NSPredicate
is, and I know this is said a lot, truly one of the jewels of Cocoa. Other languages would be lucky to have something with half of its capabilities in a third-party library—let alone the standard library. Having it as a standard-issue component affords us as application and framework developers an incredible amount of leverage in working with data.
Together with NSExpression
, NSPredicate
reminds us what a treat Foundation is: a framework that is not only incredibly useful, but meticulously architected and engineered, to be taken as inspiration for how we should write our own code.
nsmutablehipster
Questions? Corrections? Issues and pull requests are always welcome — NSHipster is made better by readers like you.
This article uses Swift version 2.0 and was last reviewed on September 19, 2015. Find status information for all articles on the status page.
original source : https://nshipster.com/nssortdescriptor/
core data에서 sort의 기본을 알수 있다.
my review point is 9/10
Sorting: it’s the mainstay of Computer Science 101 exams and whiteboarding interview questions. But when was the last time you actually needed to know how to implement Quicksort yourself?
When making apps, sorting is just something you can assume to be fast, and utility is a function of convenience and clarity of intention. And when it comes to that, you’d be hard-pressed to find a better implementation than Foundation’s NSSortDescriptor
.
NSSortDescriptor
objects are constructed with the following parameters:
key
: for a given collection, the key for the corresponding value to be sorted on for each object in the collection.ascending
: a boolean specifying whether the collection should be sorted in ascending (YES
) or descending (NO
) order.
There is an optional third parameter that relates to how the sorted values are compared to one another. By default, this is a simple equality check, but this behavior can be changed by passing either a selector
(SEL
) or comparator
(NSComparator
).
Any time you’re sorting user-facing strings, be sure to pass the selector localizedStandardCompare:
, which will sort according to the language rules of the current locale (locales may differ on ordering of case, diacritics, and so forth).
Collection classes like NSArray
and NSSet
have methods to return sorted arrays of the objects that take an array of sortDescriptors
. Sort descriptors are applied in order, so that if two elements happen to be tied for a particular sorting criteria, the tie is broken by any subsequent descriptors.
To put that into more practical terms, consider a Person
class with properties for firstName
& lastName
of type NSString *
, and age
, which is an NSUInteger
.
class Person: NSObject {
let firstName: String
let lastName: String
let age: Int
init(firstName: String, lastName: String, age: Int) {
self.firstName = firstName
self.lastName = lastName
self.age = age
}
override var description: String {
return "(firstName) (lastName)"
}
}
Given the following dataset:

Here are some of the different ways they can be sorted by combinations of NSSortDescriptor
:
let alice = Person(firstName: "Alice", lastName: "Smith", age: 24)
let bob = Person(firstName: "Bob", lastName: "Jones", age: 27)
let charlie = Person(firstName: "Charlie", lastName: "Smith", age: 33)
let quentin = Person(firstName: "Quentin", lastName: "Alberts", age: 31)
let people = [alice, bob, charlie, quentin]
let firstNameSortDescriptor = NSSortDescriptor(key: "firstName", ascending: true, selector: "localizedStandardCompare:")
let lastNameSortDescriptor = NSSortDescriptor(key: "lastName", ascending: true, selector: "localizedStandardCompare:")
let ageSortDescriptor = NSSortDescriptor(key: "age", ascending: false)
let sortedByAge = (people as NSArray).sortedArrayUsingDescriptors([ageSortDescriptor])
// "Charlie Smith", "Quentin Alberts", "Bob Jones", "Alice Smith"
let sortedByFirstName = (people as NSArray).sortedArrayUsingDescriptors([firstNameSortDescriptor])
// "Alice Smith", "Bob Jones", "Charlie Smith", "Quentin Alberts"
let sortedByLastNameFirstName = (people as NSArray).sortedArrayUsingDescriptors([lastNameSortDescriptor, firstNameSortDescriptor])
// "Quentin Alberts", "Bob Jones", "Alice Smith", "Charlie Smith"
NSSortDescriptor
can be found throughout Foundation and other system frameworks, playing an especially prominent role in Core Data. Anytime your own classes need to define sort ordering, follow the convention of specifying a sortDescriptors
parameter as appropriate.
Because, in reality, sorting should be thought of in terms of business logic, not mathematical formulas and map-reduce functions. In this respect, NSSortDescriptor
is a slam dunk, and will have you pining for it anytime you venture out of Objective-C and Cocoa.
nsmutablehipster
Questions? Corrections? Issues and pull requests are always welcome — NSHipster is made better by readers like you.
This article uses Swift version 1.1. Find status information for all articles on the status page.
How to use predicates with fetchRequest in Core Data
original source : https://stackoverflow.com/questions/41641705/how-to-use-predicates-with-fetchrequest-in-core-data
First of all get rid of all NSString
and NSDictionary
occurrences. This is Swift!. Use the Swift native structs String
and Dictionary
.
Second of all put always all good code in the do
scope of a do - catch
block.
A CoreData predicate has a simple format attribute == value
which is very similar to aContact.uniqueId! == contactIdentifierString
:
var contactIdentifierString = ""
func userSelectedContact(contactIdentifier: String) {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
do {
let fetchRequest : NSFetchRequest<Contact> = Contact.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "uniqueId == %@", contactIdentifier)
let fetchedResults = try context.fetch(fetchRequest) as! [Contact]
if let aContact = fetchedResults.first {
providerName.text = aContact.providerName
}
}
catch {
print ("fetch task failed", error)
}
}
The code assumes that there is a NSManagedObject
subclass Contact
containing
@nonobjc public class func fetchRequest() -> NSFetchRequest<Contact> {
return NSFetchRequest<Contact>(entityName: "Contact")
}
What’s new in Core Data Swift 3.0 https://blog.jayway.com/2016/08/12/whats-new-core-data-swift-3-0/
Beginner Guide to Core Data in Swift
https://www.bobthedeveloper.io/blog/beginner-guide-to-core-data-in-swift
Getting Started with Core Data Tutorial
https://www.raywenderlich.com/173972/getting-started-with-core-data-tutorial-2
CSV reading and writing library written in Swift. (3rd party library docs)
What’s new in Core Data Swift 3.0 https://blog.jayway.com/2016/08/12/whats-new-core-data-swift-3-0/
Beginner Guide to Core Data in Swift
https://www.bobthedeveloper.io/blog/beginner-guide-to-core-data-in-swift
Getting Started with Core Data Tutorial
https://www.raywenderlich.com/173972/getting-started-with-core-data-tutorial-2
CSV reading and writing library written in Swift. (3rd party library docs)