Upgrade to Pro — share decks privately, control downloads, hide ads and more …

NSPredicates for Fun and Profit

Avatar for kognate kognate
August 11, 2012
220

NSPredicates for Fun and Profit

Slides presented at CocoaConf 2012

Avatar for kognate

kognate

August 11, 2012
Tweet

Transcript

  1. What’s it for? • string stuff • filtering arrays •

    Core Data • Spotlight Friday, August 10, 12
  2. What’s it for? • string stuff • filtering • Core

    Data • Spotlight Friday, August 10, 12
  3. [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
  4. 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
  5. 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
  6. 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
  7. 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
  8. 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
  9. 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
  10. - (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
  11. - (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
  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
  13. 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
  14. 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
  15. - (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
  16. - (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
  17. 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
  18. 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
  19. 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
  20. 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
  21. You Can’t Do This select SOMETABLE.* from SOMETABLE,OTHERTABLE where SOMETABLE.column

    > 3 and OTHERTABLE.othercolumn = SOMETABLE.othercolumn; Friday, August 10, 12
  22. 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
  23. 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
  24. Don’t • use joins, use subqueries (sparingly) • confuse it

    with SQL databases • use the wrong store Friday, August 10, 12
  25. Resources • Pro Core Data for iOS • Core Data

    (Zarra) • Apple’s Docs • Practice Friday, August 10, 12