7

I'm writing a universal iOS application (iPad and iPhone) and find myself with massively long names for classes that can't be shared between the two apps:

FamilyViewController_iPhone.h/m
FamilyViewControllerA_iPad.h/m

DetailViewControllerB_iPhone.h/m
DetailViewControllerB_iPad.h/m

And likewise, the classes inside of these guys have the complete name (device included) mainly so that Interface Builder can easily use them.

I considered something like AControllerA.h and BControllerA.h where A=iPhone and B=iPad but not excited about that option either.

What is the standing convention for classes like this in an iOS universal application - or am I (hopefully) missing something that obviates this necessity?

Luther Baker
  • 7,236
  • 13
  • 46
  • 64
  • Word :) So - the driver is this... I want to leverage the iPad's unique capabilities. I don't want to pigeon hole the iPad's app to look like the iPhone's just bcs the code is easier to manage. So, no assumptions, the apps may look different and act different and have different screenflows/wizards, etc - just the nature of the beast. I guess I could just use radically different names for the classes and not even try to identify common functionality in the class name ... – Luther Baker Mar 06 '11 at 17:00

3 Answers3

4

I think you're heading down a bad path by separating your functionality like this. While iPad apps can obviously have different UI structures and design from your iPhone apps, but it's really best if you can try to remain as abstract as possible.

I avoid using platform names in my view controllers. I'd have:

FamilyViewController.h
FamilyViewController.m
FamilyViewController.xib (which is used for the iPad UI)
FamilyViewController~iphone.xib

You're most likely going to have incredibly similar functionality for both iPhone and iPad, or if not the same, you'll still have a lot of overlap.

I also never make my view controllers act as my table controllers. I keep that functionality in separate objects. That way, if the iPhone app has 2 or 3 tables on different screens, but the iPad shows all 3 of those tables on the same screen you can just instantiate each of those table controllers and all of the code is reusable.

Kenny Wyland
  • 20,844
  • 26
  • 117
  • 229
  • I'm afraid of a use case where something like the detail view for the iPad ends up being wildly different than the detail view for iPhone. I often use a UITableView on the iPhone as an editor template - but I generally don't do that on the iPad. The logic to manage a UITableView would be crazy to push inside a View Controller that also manages logic for a larger screen XIB based editor for the iPad. To take advantage of the iPad's larger screen - I often end up with very different logic and screenflow. It isn't always very clean to reuse the same classes as you described. – Luther Baker Mar 06 '11 at 16:54
  • First, I never put my table datasource and delegate code into a view controller. I've found that is just pain waiting to happen. Break the datasource and delegate out into a separate class. Yes, sometimes the functionality is very different. If so, I'll make two IBAction methods and bind one to the iPhone xib and one to the iPad xib. The functionality in those methods will still no doubt share SOME bits and I make sure to break those out into separate methods so they can be called from both IBAction methods. – Kenny Wyland Mar 06 '11 at 18:22
2

If you want to use the same class YourClass with YourClass.xib and YourClass-iPad.xib, then check out this macro that I use:

#define getXIB(s) ( (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) ? @"" #s "-iPad" :@"" #s )

So you can then use the class itself to get the proper XIB file:

YourClass * viewController = [[YourClass alloc] initWithNibName:getXIB(YourClass) bundle:nil];
pyramation
  • 1,631
  • 4
  • 22
  • 35
1

I'm not sure there's a standard way to handle this.

One possibility is to use a class cluster-like strategy. If FamilyViewController_iPad and FamilyViewController_iPhone are very similar, then make them subclasses of an abstract FamilyViewController class. Set up the -initWithNibName:bundle: method of FamilyViewController such that it returns an instance of either the ...iPad or ...iPhone version, depending on which device the app is running on. In most of your code, then, you'll only deal with FamilyViewController. You'll still need to use the subclass name in your nibs, of course, but at least your code will be easier to read.

Caleb
  • 124,013
  • 19
  • 183
  • 272
  • Yep - this is definitely my starting point. Just not sure if there was a standard practice for when you have an EditorView ... that is just wildly different between the two platforms (iPhone might use a UITableView whereas an iPad might use a custom XIB with all the fields laid out like a form). – Luther Baker Mar 06 '11 at 16:57