Reputation: 7432
I've got a universal iOS app that I've been working on. For the most part, I've been handling device differences by creating subclasses, so RootViewController is subclassed by RootViewController-iPad and RootViewController-iPhone. The pattern starts in main.m, where I do device detection as follows:
int retVal;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
retVal = UIApplicationMain(argc, argv, nil, @"SalesPadAppDelegate_iPad");
} else {
retVal = UIApplicationMain(argc, argv, nil, @"SalesPadAppDelegate_iPhone");
}
This pattern is working quite well, and is minimize code reuse.
Further down the stack, I've got a series of view controllers that inherit from a common superclass, MasterDetailViewController. This superclass needs some device specific code, so I was thinking of subclassing that, and then ending up with the superclass automatically allocating or instantiating the device specific subclass that's most suitable.
Implementation wise, this looks like the following:
+(id)allocWithZone:(NSZone *)zone {
if ([[self class] isEqual:[MasterDetailViewController_iPad class]] || [[self class] isEqual:[MasterDetailViewController_iPhone class]]) {
return [super allocWithZone:zone];
} else {
if ([[UIDevice currentDevice] userInterfaceIdiom]==UIUserInterfaceIdiomPhone) {
return [MasterDetailViewController_iPhone allocWithZone:zone];
} else {
return [MasterDetailViewController_iPad allocWithZone:zone];
}
}
}
This code doesn't work, and is kind of a demonstration of concept. Is there a way to do what I'm trying to do, or am I looking at things all wrong?
EDIT: Just to be clear, the data is the same between the super and subclasses. The only difference would be a couple of method implementations. The idea being that subclassing is cleaner than device specific spaghetti code.
Upvotes: 1
Views: 1092
Reputation: 94794
Chances are your code isn't working because self
inside a class method is the class object, so [self class]
is the class of the class. Try just [self isEqual:[MasterDetailViewController_iPad class]]
instead. You could also turn around the comparison, something like this:
+ (id)allocWithZone:(NSZone *)zone {
// Allocating a subclass, don't interfere
if (![self isEqual:[MasterDetailViewController class]]) {
return [super allocWithZone:zone];
}
// Select an appropriate subclass to create instead
if ([[UIDevice currentDevice] userInterfaceIdiom]==UIUserInterfaceIdiomPhone) {
return [MasterDetailViewController_iPhone allocWithZone:zone];
} else {
return [MasterDetailViewController_iPad allocWithZone:zone];
}
}
That might be a little easier to extend, if you ever have reason for more device-specific subclasses.
Note that there are other ways to do this. For example, instead of device-specific subclasses, the one general class could allocate and use a device-specific helper object to handle the few operations that need to be different (sort of like a delegate). Or, instead of overriding allocWithZone:, you could have the base class's init
method release self
and instead allocate and return a new object of the appropriate subclass. Or you could use a factory method to allocate the appropriate device-specific subclass.
Upvotes: 1