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
260
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
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
310
How STYLIGHT went responsive
nonsquared
100
6.2k
What's in a price? How to price your products and services
michaelherold
247
13k
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.4k
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
62
44k
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
3
930
Navigating the Design Leadership Dip - Product Design Week Design Leaders+ Conference 2024
apolaine
1
370
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.4k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
230
23k
New Earth Scene 8
popppiees
3
2.4k
A brief & incomplete history of UX Design for the World Wide Web: 1989–2019
jct
2
420
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
55k
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