Skip to content

Instantly share code, notes, and snippets.

@gprasant
Last active September 19, 2016 23:00
Show Gist options
  • Save gprasant/209836a1a3d4b7a31c855a775bf74264 to your computer and use it in GitHub Desktop.
Save gprasant/209836a1a3d4b7a31c855a775bf74264 to your computer and use it in GitHub Desktop.
Avoiding Stringly Typed Programming - Filtering
NSMutableArray *people = @[person1, person2, person3];
// Option 1:Filtering with Strings
NSPredicate *gt_1M = [NSPredicate predicateWithFormat:@"heightInMeters > 1.0"];
NSArray *tallFolks = [people filteredArrayUsingPredicate:gt_1M];
for (BNRPerson *p in tallFolks) {
NSLog(@"<Height: %f>", p.heightInMeters);
}
// -----------------
// Option 2: Filtering with Blocks
// Step 1. Make a predicate Block
NSPredicate *gt_1M_block = [NSPredicate predicateWithBlock:^BOOL(BNRPerson *_Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
if ([evaluatedObject heightInMeters] > 1.0) {
return YES;
} else {
return NO;
}
}];
// Step 2: Use block in filter Method
NSArray *tallFolks_block = [people filteredArrayUsingPredicate:gt_1M_block];
for (BNRPerson *p in tallFolks_block) {
NSLog(@"<Height: %f>", [p heightInMeters]);
}
@gprasant
Copy link
Author

My thoughts on the matter:
Option 1: (filtering with Strings) is prone to mistyping and you wont figure out that theres a problem until you run a test or the app fails throwing an exception.

Option 2: Filtering with blocks - it is possible to strongly type the args to the predicate, thereby catching mistakes during the compilation phase.

@daniel-beard
Copy link

What about an approach that doesn't use NSPredicate at all?

        NSArray *array = @[@2, @4, @5, @6];
        NSIndexSet *set = [array indexesOfObjectsPassingTest:^BOOL (id obj, NSUInteger idx, BOOL * stop) {
            return [obj integerValue] < 6;
        }];
        NSArray *subArray = [array objectsAtIndexes:set];

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment