Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
NSPredicates for Fun and Profit
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
kognate
August 11, 2012
250
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
NSPredicates for Fun and Profit
Slides presented at CocoaConf 2012
kognate
August 11, 2012
More Decks by kognate
See All by kognate
DSLs And Extension Languages
kognate
1
130
CodeMash Prolog Talk 2012
kognate
3
230
Featured
See All Featured
GraphQLとの向き合い方2022年版
quramy
50
15k
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
BBQ
matthewcrist
89
10k
svc-hook: hooking system calls on ARM64 by binary rewriting
retrage
2
290
Rails Girls Zürich Keynote
gr2m
96
14k
Neural Spatial Audio Processing for Sound Field Analysis and Control
skoyamalab
0
320
Being A Developer After 40
akosma
91
590k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
1.9k
Evolving SEO for Evolving Search Engines
ryanjones
0
210
Context Engineering - Making Every Token Count
addyosmani
9
940
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1.2k
Transcript
NSPredicates For Fun and Profit Friday, August 10, 12
An NSPredicate is a Query Friday, August 10, 12
What’s it for? • string stuff • filtering arrays •
Core Data • Spotlight Friday, August 10, 12
It’s in Foundation Friday, August 10, 12
What’s it for? • string stuff • filtering • Core
Data • Spotlight Friday, August 10, 12
Creating NSPredicates Friday, August 10, 12
[NSPredicate predicateWithFormat:@”FORMAT_STRING”,args] Friday, August 10, 12
[NSPredicate predicateWithFormat:@”SELF contains %@”,@”hello”] Friday, August 10, 12
[NSPredicate predicateWithFormat:@”SELF contains %@”,@”hello”] NSPredicate *greeting = [NSPredicate predicateWithFormat:@"SELF contains
%@",@"hello"]; BOOL greeted = [greeting evaluateWithObject:@"hello world"]; NSLog(@"Greeted? %d",greeted); Friday, August 10, 12
String Matching BEGINSWITH CONTAINS ENDSWITH LIKE MATCHES Friday, August 10,
12
String Matching BEGINSWITH CONTAINS ENDSWITH LIKE MATCHES Friday, August 10,
12
BEGINSWITH NSPredicate *beginswith = [NSPredicate predicateWithFormat:@"self beginswith %@",@"begins"]; NSLog(@"Begins with:
%d",[beginswith evaluateWithObject:@"beginswith"]); NSLog(@"Begins with: %d",[beginswith evaluateWithObject:@"wbeginswith"]); Friday, August 10, 12
String Matching BEGINSWITH CONTAINS ENDSWITH LIKE MATCHES Friday, August 10,
12
CONTAINS NSPredicate *contains = [NSPredicate predicateWithFormat:@"self contains[cd] %@",@"past"]; NSLog(@"Contains string:
%d", [contains evaluateWithObject:@"The past isn't done with you"]); NSLog(@"Contains string: %d",[contains evaluateWithObject:@"PaSt"]); Friday, August 10, 12
String Matching BEGINSWITH CONTAINS ENDSWITH LIKE MATCHES Friday, August 10,
12
ENDSWITH NSPredicate *endswith = [NSPredicate predicateWithFormat:@"self endswith %@",@"world"]; NSLog(@"Endswith string:
%d",[endswith evaluateWithObject:@"hello world"]); NSLog(@"Endswith string: %d",[endswith evaluateWithObject:@"hello world?"]); Friday, August 10, 12
String Matching BEGINSWITH CONTAINS ENDSWITH LIKE MATCHES Friday, August 10,
12
LIKE NSPredicate *like = [NSPredicate predicateWithFormat:@"self lik %@",@"*like?"]; NSLog(@"Is Like:
%d", [like evaluateWithObject:@"likeable"]); NSLog(@"Is Like: %d", [like evaluateWithObject:@"is likeable"]) NSLog(@"Is Like: %d", [like evaluateWithObject:@"likes"]); NSLog(@"Is Like: %d", [like evaluateWithObject:@"wiliked"]); Friday, August 10, 12
String Matching BEGINSWITH CONTAINS ENDSWITH LIKE MATCHES Friday, August 10,
12
MATCHES NSPredicate *match = [NSPredicate predicateWithFormat:@"self matches '\\\\d+[a-z]'"]; NSLog(@"Regex match:
%d", [match evaluateWithObject:@"0A"]); NSLog(@"Regex match: %d", [match evaluateWithObject:@"0a"]); NSLog(@"Regex match: %d", [match evaluateWithObject:@"000000ab"]); NSLog(@"Regex match: %d", [match evaluateWithObject:@"000000c"]); Friday, August 10, 12
Strings • String begins with ‘CH’ • longer than 3
chars • does NOT contain ‘broken’ • shorter than 20 chars • contains at least one digit • contains NO spaces Friday, August 10, 12
- (BOOL) thisIsTerrible:(NSString *) _myarg { BOOL _res = NO;
if ([[_myarg substringToIndex:2] isEqualToString:@"CH"]) { if ([_myarg length] > 3) { if ([[_myarg componentsSeparatedByString:@"broken"] count] 1) { if ([_myarg length] < 20) { NSCharacterSet *s = [NSCharacterSet decimalDigitCharacterSet]; if ([[_myarg componentsSeparatedByCharactersInSet: count] > 1) { if ([[_myarg componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] count] == 1) { _res = YES; } } } } } } return _res; } Friday, August 10, 12
- (BOOL) predicatesTIT:(NSString *)_myarg { NSPredicate *beginsWithCH = [NSPredicate predicateWithFormat:@"SELF
beginswith 'CH'"]; NSPredicate *longEnough = [NSPredicate predicateWithFormat:@"SELF.length > 3"]; NSPredicate *shortEnough = [NSPredicate predicateWithFormat:@"SELF.length < 20"]; NSPredicate *containsDigit = [NSPredicate predicateWithFormat:@"SELF matches '.* \\\\d.*'"]; NSPredicate *containsSpace = [NSPredicate predicateWithFormat:@"SELF contains ' '"]; NSPredicate *containsBroken = [NSPredicate predicateWithFormat:@"SELF contains 'broken'"]; NSPredicate *notContainsBroken = [NSCompoundPredicate notPredicateWithSubpredicate:containsBroken]; NSPredicate *notCOntainsSpace = [NSCompoundPredicate notPredicateWithSubpredicate:containsSpace]; NSArray *_preds = [NSArray arrayWithObjects:beginsWithCH, longEnough, shortEnough, notContainsBroken, notCOntainsString, containsDigit, nil]; NSPredicate *main = [NSCompoundPredicate andPredicateWithSubpredicates:_preds]; return [main evaluateWithObject:_myarg]; } Friday, August 10, 12
- (BOOL) predicatesTITshort:(NSString *)_myarg { NSPredicate *one = [NSPredicate predicateWithFormat:@"SELF
beginswith 'CH'"]; NSPredicate *two = [NSPredicate predicateWithFormat:@"SELF.length > 3 AND self.length < 20"]; NSPredicate *three = [NSPredicate predicateWithFormat:@"SELF matches '.*\\\\d.*' and NOT(SELF contains ' ') and NOT(SELF contains 'broken')"]; NSArray *_preds = [NSArray arrayWithObjects:one,two,three,nil]; NSPredicate *main = [NSCompoundPredicate andPredicateWithSubpredicates:_preds]; return [main evaluateWithObject:_myarg]; } Friday, August 10, 12
But then things change Friday, August 10, 12
Strings • String begins with ‘CH’ • longer than 3
chars • does NOT contain ‘broken’ • shorter than 20 chars • contains at least one digit • contains NO spaces Friday, August 10, 12
Strings • String begins with ‘CH’ or ‘HC’ • longer
than 3 chars • does NOT contain ‘broken’ • contains ‘broken’ if string starts with ‘HC’ • shorter than 20 chars • contains at least one digit • contains NO spaces Friday, August 10, 12
- (BOOL) thisIsReallyTerrible:(NSString *)_myarg { BOOL _res = NO; if
([_myarg length] > 3) { if ([_myarg length] < 20) { NSCharacterSet *s = [NSCharacterSet decimalDigitCharacterSet]; if ([[_myarg componentsSeparatedByCharactersInSet:s] count] > 1) { NSCharacterSet *w = [NSCharacterSet whitespaceCharacterSet]; if ([[_myarg componentsSeparatedByCharactersInSet:w] count] == 1) { if ([[_myarg substringToIndex:2] isEqualToString:@"CH"]) { if ([[_myarg componentsSeparatedByString:@"broken"] count] == 1) { _res = YES; } } else if ([[_myarg substringToIndex:2] isEqualToString:@"HC"]) { if ([[_myarg componentsSeparatedByString:@"broken"] count] > 1) { _res = YES; } } } } } } return _res; } Friday, August 10, 12
- (BOOL) predicatesTIRT:(NSString *)_myarg { NSPredicate *beginsWithCH = [NSPredicate predicateWithFormat:@"SELF
beginswith 'CH'"]; NSPredicate *beginsWithHC = [NSPredicate predicateWithFormat:@"SELF beginswith 'HC'"]; NSPredicate *longEnough = [NSPredicate predicateWithFormat:@"SELF.length > 3"]; NSPredicate *shortEnough = [NSPredicate predicateWithFormat:@"SELF.length < 20"]; NSPredicate *containsDigit = [NSPredicate predicateWithFormat:@"SELF matches '.*\\\\d.*'"]; NSPredicate *containsSpace = [NSPredicate predicateWithFormat:@"SELF contains ' '"]; NSPredicate *containsBroken = [NSPredicate predicateWithFormat:@"SELF contains 'broken'"]; NSPredicate *notCB = [NSCompoundPredicate notPredicateWithSubpredicate:containsBroken]; NSPredicate *notCS = [NSCompoundPredicate notPredicateWithSubpredicate:containsSpace]; NSArray *_ch = [NSArray arrayWithObjects:beginsWithCH,notCB, nil]; NSPredicate *chnotbroken = [NSCompoundPredicate andPredicateWithSubpredicates:_ch]; NSArray *_hc = [NSArray arrayWithObjects:beginsWithHC,containsBroken,nil]; NSPredicate *hcbroken = [NSCompoundPredicate andPredicateWithSubpredicates:_hc]; NSArray *_chhc = [NSArray arrayWithObjects:chnotbroken,hcbroken, nil]; NSPredicate *begins = [NSCompoundPredicate orPredicateWithSubpredicates:_chhc]; NSArray *_preds = [NSArray arrayWithObjects:begins, longEnough, shortEnough, containsDigit, notCS, nil]; NSPredicate *main = [NSCompoundPredicate andPredicateWithSubpredicates:_preds]; return [main evaluateWithObject:_myarg]; } Friday, August 10, 12
MATCHES validation NSPredicate *_emailValid = [NSPredicate predicateWithFormat:@"self matches '[a-z+] +@[a-z]+\\\\.com'"];
return [_emailValid evaluateWithObject:email]; Friday, August 10, 12
Filtering Arrays • mutable and immutable • works great for
table views Friday, August 10, 12
Simple Filtering NSArray *_start = [NSArray arrayWithObjects:NSNum(1),NSNum(3),NSNum(5),NSNum(7),NSNum(8),ni l]; NSPredicate *_filter
= [NSPredicate predicateWithFormat:@"self in {1,5,7}"]; return [_start filteredArrayUsingPredicate:_filter]; #define NSNum(arg) [NSNumber numberWithInt:arg] Friday, August 10, 12
Mutable Filter NSPredicate *_filter = [NSPredicate predicateWithFormat:@"self in {1,5,7}"]; [_mutable
filterUsingPredicate:_filter]; Friday, August 10, 12
Key Paths NSDictionary *_done = [NSDictionary dictionaryWithObjectsAndKeys: @"Sam", @"Firstname", [NSDate
date],@"Birthday", nil]; NSDictionary *_dtwo = [NSDictionary dictionaryWithObjectsAndKeys:@"Alice",@"Firstname",[NSDate date],@"Birthday", nil]; NSDictionary *_dthree = [NSDictionary dictionaryWithObjectsAndKeys:@"Amy",@"Firstname",nil]; NSArray *_ar = [NSArray arrayWithObjects:_done,_dtwo,_dthree,nil]; NSPredicate *_pred = [NSPredicate predicateWithFormat:@"Birthday != nil && Firstname != nil"]; NSArray *_res = [_ar filteredArrayUsingPredicate:_pred]; NSLog(@"%@",_res); return _res; Friday, August 10, 12
Not All Keys Nest NSDictionary *_ndone = [NSDictionary dictionaryWithObjectsAndKeys:[NSDate date],@"Date",
nil]; NSDictionary *_done = [NSDictionary dictionaryWithObjectsAndKeys:@"Sam",@"Firstname",_ndone,@"Birthday", nil]; NSDictionary *_dtwo = [NSDictionary dictionaryWithObjectsAndKeys:@"Alice",@"Firstname",[NSDate date],@"Birthday", nil]; NSDictionary *_dthree = [NSDictionary dictionaryWithObjectsAndKeys:@"Amy",@"Firstname",nil]; NSArray *_ar = [NSArray arrayWithObjects:_done,_dtwo,_dthree,nil]; NSPredicate *_pred = [NSPredicate predicateWithFormat:@"Birthday.Date != nil && Firstname != nil"]; NSArray *_res = [_ar filteredArrayUsingPredicate:_pred]; return _res; Friday, August 10, 12
Other ways to define NSPredicate *_pred = [NSPredicate predicateWithBlock:^BOOL(NSArray *obj,
NSDictionary *bindings) { BOOL _lengthGood = [obj count] > 3; NSUInteger idx = [obj indexOfObject:[NSNumber numberWithInt:20]]; return _lengthGood && idx; }]; return [_pred evaluateWithObject:_array]; Friday, August 10, 12
Core Data IS NOT SQL Friday, August 10, 12
You Can’t Do This select SOMETABLE.* from SOMETABLE,OTHERTABLE where SOMETABLE.column
> 3 and OTHERTABLE.othercolumn = SOMETABLE.othercolumn; Friday, August 10, 12
Object Graph Friday, August 10, 12
Friday, August 10, 12
Subquery NSFetchRequest *_fetch = [[NSFetchRequest alloc] init]; NSPredicate *_pred =
[NSPredicate predicateWithFormat: @"manager.name = 'Bill' and subquery(Employee,$e, any $e.salary > 90000)@count > 1"]; [_fetch setPredicate:_pred]; NSManagedObjectContext *context = [self managedObjectContext]; NSError *error = nil; return [[context executeFetchRequest:_fetch error:&error] lastObject]; Friday, August 10, 12
Don’t Friday, August 10, 12
Core Data Validation - (BOOL)validateValue:(id *)ioValue forKey:(NSString *)key error:(NSError **)outError
Friday, August 10, 12
Performance • It’s very fast • But it’s not magic
Friday, August 10, 12
Do • minimize the amount of work done • put
‘match’ last • avoid joins • denormalize performance sensitive data • use the right store for the right job Friday, August 10, 12
Don’t • use joins, use subqueries (sparingly) • confuse it
with SQL databases • use the wrong store Friday, August 10, 12
Remember The Compiler Can Do It Better Friday, August 10,
12
Resources • Pro Core Data for iOS • Core Data
(Zarra) • Apple’s Docs • Practice Friday, August 10, 12