A Cluster to Remove Clutter
I recently spoke at our monthly CocoaHeads MeetUp in Cleveland about using Class Clusters to be able to abstract away some implementation details of checking whether the device running your app is iOS 6 or iOS 7, which also gives you a lot of other benefits too. I promised a blog post, so here it is.
What Is A Class Cluster?
Why?
A few things come to mind:
Makes it simpler to support an older iOS, different hardware, etc
Cleans code of frequent if-then checks
Allows easy integration of newer iOS version-aware classes without modifying much/any of your existing code
A Use Case
When deciding if I wanted to support both iOS 6 and iOS 7 with both an app I have in the App Store and an app I'm working on, I did some digging around, and found a post by Jean-David Gadina (http://www.noxeos.com/2013/06/18/strategies-support-ios7-ui/) incredibly helpful for making your code support both versions of the OS without needing to write a bunch of if-then's in your code. I was also at the time monkeying around with the new UISearchDisplayController goodness of having them embedded in navigation bars in iOS 7 and wondering why it would work on the iPhone but not the iPad. After quite a bit of banging my head on the desk, and reading and re-reading Apple's docs on UISDC, I looked around the internets, and found an article by Peter Steinberger (http://petersteinberger.com/blog/2013/fixing-uisearchdisplaycontroller-on-ios-7/) where he described what he did to fix the UISDC on iOS 7 iPad version. And then I had my "a ha" moment -- I could use Class Clusters to figure out which iOS was running, and display a UISDC accordingly. So let's do it.
The Code.
The code is available on my GitHub page (https://github.com/SixFiveSoftware/ClusterDemo), if you'd like to look at it; I will quickly run through the steps of creating it here. Since I suggest downloading the code, I won't cover absolutely everything to make a working app here, just the pertinent parts.
Firstly, create a category on UIDevice to return the system major version (i.e., '6' or '7', or '8' in the future, etc.). Create a new file, a Category on UIDevice, called UIDevice+VersionCheck. You'll want to declare the method in your .h interface:
- (NSUInteger)systemMajorVersion;
Then, in your .m implementation file, type this method:
- (NSUInteger)systemMajorVersion { NSString *versionString = [self systemVersion]; return (NSUInteger)[versionString doubleValue]; }
Next, let's create the cluster. Because I wanted this to display search results, create a new subclass of UITableViewController, and call it whatever you want to make it (hint: keep it general, like Apple did with NSArray, NSNumber, etc.). Here, I made mine SFSSearchTVC. Then, create two more classes, each one a subclass of SFSSearchTVC (or whatever you called yours). I called my SFSSearchTVC6 and SFSSearchTVC7, for (you guessed it) iOS 6 and iOS 7. The reason we want to subclass is so that we can reuse methods because of inheritance.
Since iOS 6 search display controllers didn't suck, we won't have to do much to the iOS 6 subclass. The iOS 7 one, however, takes some work. Let's first do that voodoo to make the cluster work.
Open SFSSearchTVC and override -alloc:
+ (id)alloc { if ([self class] == [SFSSearchTVC class]) { if ([UIDevice currentDevice] systemMajorVersion] < 7) { return [SFSSearchTVC6 alloc]; } else if ([UIDevice currentDevice] systemMajorVersion] == 7) { return [SFSSearchTVC7 alloc]; } } return [super alloc]; }
This method gets called first thing when the you need an SFSSearchTVC object, so you override this method to direct it to which class to return. A lot easier than you thought, isn't it? Basically it's checking your systemMajorVersion and returning the appropriate subclass; if none of these are true, it just simply returns[super alloc].
Now, just customize the iOS 6 and iOS 7 subclasses how you want them, and when you alloc/init an SFSSearchTVC object, you'll get one according to your iOS version!
Wrap Up
At this point, download the code from https://github.com/SixFiveSoftware/ClusterDemo and play around with it yourself. You'll see that the SFSSearchTVC is the UISearchBar delegate, but not the UISearchDisplayController delegate; it leaves that to each subclass for how to handle that.
Hope this helps!
Twitter: http://twitter.com/bjmillerltd. App.net: http://app.net/bjmiller












