-
-
Save evanlong/1692489 to your computer and use it in GitHub Desktop.
// Started here | |
class Reader : NSObject {} | |
class PDFReader_Shared : Reader {} | |
class PDFReader_iPad : PDFReader_Shared {} | |
class PDFReader_iPhone : PDFReader_Shared {} | |
class TextReader_Shared : Reader {} | |
class TextReader_iPad : TextReader_Shared {} | |
class TextReader_iPhone : TextReader_Shared {} | |
///// | |
Now I want Reader to have iPad/iPhone specifics. In the WPF/Silverlight land I could solve this | |
with partial classes. To be fair it was all solved at compile time. Basically have 3 directores: | |
Shared, WPF, Silverlight. Then one build would do the partial classes of Shared+WPF and the | |
other was Shared+Silverlight. | |
For iOS this would need to be a runtime thing. Picking up the right Reader base class. | |
//// | |
class Reader_Shared : NSObject {} | |
class Reader_iPad : Reader_Shared {} | |
class Reader_iPhone : Reader_iPad {} | |
Now what would the PDFReader_Shared and TextReader_Shared derive from? It would need to be change | |
at runtime I guess which is scary (not sure if it's possible?) | |
The "started here" class hierarchy is how the app currently is. And it works quite well for going down different code paths based on device. We also don't have a whole lot of those if checks as a result because we only do it at the alloc init of a class.
For example lets say on iPhone and iPad we show a UIAlertView then the code to deal with presenting and handling interaction likely ends up in Shared. Now lets say they hit "Ok" on the alert and we want to do something different depending on the device type. So in the Shared code handler for the alert view we could check the userInterfaceIdiom and run different code or call a platform specific method in the category.
The approach we take to handle this user interaction would be to call [self performOkAction]
from the Shared class. Shared may or may not provide a default implementation depending on the situation. But the subclasses for iPhone and iPad contain code for that device. So at runtime the call to performOkAction
method specific to a device. Polymorphism FTW :).
So this works with the shallow class hierarchy. Make it bigger now its funky if the class up the chain needs to be iPad/iPhone.
You could implement a class cluster. You’d only expose the @interface
for the main class in the public header. The implementation file would look like this:
@interface iPhoneClass : MyClass
// iPhone methods defined here
@end
@implementation iPhoneClass
// iPhone methods defined here
@end
@interface iPadClass : MyClass
// iPad methods defined here
@end
@implementation iPadClass
// iPad methods implemented here
@end
@implementation MyClass
+ (id)alloc
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
return [iPadClass alloc];
}
else {
return [iPhoneClass alloc];
}
}
// Shared methods go here
@end
If you don’t add any instance variables to iPhoneClass
or iPadClass
, you can skip implementing alloc
, as their memory layout will be equivalent.
It seems to me that your real problem is that you want to go down different code paths for iPhone and iPad. Without specifics of why you need to do this, you can always do it in code like this:
Now, if you want to separate the code into different files, you would use categories. The header file:
While it’s technically feasible to do this all at runtime and resolve methods dynamically based on the device, it's a lot more work and a lot less idiomatic for the platform.