Es ist möglich, dass ein Storyboard verschiedene Unterklassen eines benutzerdefinierten Ansichts-Controllers instanziiert, obwohl dies eine etwas unorthodoxe Technik beinhaltet: Überschreiben der alloc
Methode für den Ansichts-Controller. Wenn der benutzerdefinierte Ansichtscontroller erstellt wird, gibt die überschriebene Zuweisungsmethode tatsächlich das Ergebnis der Ausführung alloc
in der Unterklasse zurück.
Ich sollte der Antwort den Vorbehalt voranstellen, dass ich, obwohl ich sie in verschiedenen Szenarien getestet und keine Fehler erhalten habe, nicht sicherstellen kann, dass sie mit komplexeren Einstellungen fertig wird (aber ich sehe keinen Grund, warum sie nicht funktionieren sollte). . Außerdem habe ich keine Apps mit dieser Methode eingereicht, sodass die Möglichkeit besteht, dass sie vom Überprüfungsprozess von Apple abgelehnt werden (auch hier sehe ich keinen Grund, warum dies der Fall sein sollte).
Zu Demonstrationszwecken habe ich eine Unterklasse von UIViewController
aufgerufen TestViewController
, die ein UILabel IBOutlet und eine IBAction hat. In meinem Storyboard habe ich einen View Controller hinzugefügt und seine Klasse geändert TestViewController
und das IBOutlet mit einem UILabel und die IBAction mit einem UIButton verbunden. Ich präsentiere den TestViewController über einen modalen Übergang, der durch einen UIButton auf dem vorhergehenden viewController ausgelöst wird.
Um zu steuern, welche Klasse instanziiert wird, habe ich eine statische Variable und zugehörige Klassenmethoden hinzugefügt, um die zu verwendende Unterklasse abzurufen / festzulegen (ich denke, man könnte andere Methoden anwenden, um zu bestimmen, welche Unterklasse instanziiert werden soll):
TestViewController.m:
#import "TestViewController.h"
@interface TestViewController ()
@end
@implementation TestViewController
static NSString *_classForStoryboard;
+(NSString *)classForStoryboard {
return [_classForStoryboard copy];
}
+(void)setClassForStoryBoard:(NSString *)classString {
if ([NSClassFromString(classString) isSubclassOfClass:[self class]]) {
_classForStoryboard = [classString copy];
} else {
NSLog(@"Warning: %@ is not a subclass of %@, reverting to base class", classString, NSStringFromClass([self class]));
_classForStoryboard = nil;
}
}
+(instancetype)alloc {
if (_classForStoryboard == nil) {
return [super alloc];
} else {
if (NSClassFromString(_classForStoryboard) != [self class]) {
TestViewController *subclassedVC = [NSClassFromString(_classForStoryboard) alloc];
return subclassedVC;
} else {
return [super alloc];
}
}
}
Für meinen Test habe ich zwei Unterklassen von TestViewController
: RedTestViewController
und GreenTestViewController
. Die Unterklassen verfügen jeweils über zusätzliche Eigenschaften und werden überschrieben viewDidLoad
, um die Hintergrundfarbe der Ansicht zu ändern und den Text des UILabel IBOutlet zu aktualisieren:
RedTestViewController.m:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor redColor];
self.testLabel.text = @"Set by RedTestVC";
}
GreenTestViewController.m:
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor greenColor];
self.testLabel.text = @"Set by GreenTestVC";
}
In einigen Fällen möchte ich mich vielleicht TestViewController
selbst instanziieren , in anderen Fällen RedTestViewController
oder GreenTestViewController
. In der vorhergehenden Ansichtssteuerung mache ich dies zufällig wie folgt:
NSInteger vcIndex = arc4random_uniform(4);
if (vcIndex == 0) {
NSLog(@"Chose TestVC");
[TestViewController setClassForStoryBoard:@"TestViewController"];
} else if (vcIndex == 1) {
NSLog(@"Chose RedVC");
[TestViewController setClassForStoryBoard:@"RedTestViewController"];
} else if (vcIndex == 2) {
NSLog(@"Chose BlueVC");
[TestViewController setClassForStoryBoard:@"BlueTestViewController"];
} else {
NSLog(@"Chose GreenVC");
[TestViewController setClassForStoryBoard:@"GreenTestViewController"];
}
Beachten Sie, dass die setClassForStoryBoard
Methode überprüft, ob der angeforderte Klassenname tatsächlich eine Unterklasse von TestViewController ist, um Verwechslungen zu vermeiden. Der obige Verweis auf BlueTestViewController
dient zum Testen dieser Funktionalität.