Passing the NSArray Test

The Setup and Crash

The other night I was working on the event image gallery for WhoNote and stumbled upon an interesting scenario. I am using UIPageViewController instead of an infinite UIScrollview to mimic the native photo app, I created a POC for this when I was at the WWDC so I thought I could just reuse that.


The source of the crash wasn’t immediately obvious. I setup the controller properly and made all the necessary delegate/datasource associations. What was the problem? Turns out that in the the POC my image array was populated with photo objects, but the image array I’m passing around in WhoNote between view controllers contains NSDictionaries.

Consequently, when calling

NSUInteger currentIndex = [self.imageArray indexOfObject:currentPhotoObject];

I get an index that is not only out of bounds, but an incorrect object. The reason for getting the index of the object is that I can handle the forward and backwards pagination with the UIPageViewController and which image to display.

Time to rethink my implemenation approach.


The first avenue I went for was NSPredicate. Though the background of NSPredicate is out-of-scope for this article I would suggest reading Cocoanetics’ Filtering Fun with Predicates for some pretty interesting usages of this class.

Search Criteria

Because I don’t have instances of WNPhoto in my array I needed a way to efficiently search the array of dictionaries for a specific key value and then stop.

Example of values:

Finding a predicate to satisify my search requirements was easy:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(ffUrl ==  %@)", @"ffUrlToPhoto"];
NSArray *filteredArray = [data filteredArrayUsingPredicate:predicate];

But that didn’t do me any good with the UIPageViewController pagination because now I an array with only one element. I really didnt’ want have to write some less than optimatal iterator to manually search the array for the value I was looking for.

When In Doubt Read the Docs

The methods that Apple provides for NSArray are extensive, and while on the surface it might appear they could be duplicated I’m going to go ahead and say that the engineers at Apple are smarter than me and figured out the best ways to find the needle in the haystack.


Returns the index of an object in the array that passes a test in a given Block for a given set of enumeration options.

Sounds good to me. I do feel the method signature could be improved, but that is for another discussion. After fumbling the syntax a couple of times I ended up with logic that provided the solution I was needing without having to mutate the original dataset. More importantly I learned something new.

NSUInteger currentIndex = [self.imageArray indexOfObjectWithOptions:NSEnumerationConcurrent passingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop)  {
       NSDictionary *metaDict = (NSDictionary *)obj;

       if ([metaDict[@"ffUrl"] isEqualToString:metaData.ffUrl]) {

         *stop = YES;

        return *stop;

     return NO;

From Baby Showers to Banaroo

WhoNote might not have floated to the next $250,000 round pitch, but it did float it’s way into the public. Last night I presented to a packed 4th Floor at the Chattanooga Library on my latest project, WhoNote. It was an amazing experience in every aspect. Hearing some pretty kick-ass ideas being presented, the warm reception from the crowd and decor.

It didn’t hurt that ChattanoogaWhiskey and Fork and Pie provided the food and beverages either :)

So what’s next? Finishing the app of course. I took the past week off from development to work on the pitch, but with a renewed sense of purpose and excitement I’m back on it. Working closely with FatFractal as the BaaS provider and the time spent making the UI as simple/easy to use I believe the final product will be a joy to use.

Don’t forget to signup at for updates on the development and launch.

A huge thanks to my close friend Scott Wills for all the design work on WhoNote. Couldn’t be happier with how it is taking shape.

If you are interested in seeing the desk then hop over to Speaker Deck.