Il est possible qu'un storyboard instancie différentes sous-classes d'un contrôleur de vue personnalisé, bien que cela implique une technique légèrement peu orthodoxe: remplacer la alloc
méthode pour le contrôleur de vue. Lorsque le contrôleur de vue personnalisé est créé, la méthode d'allocation remplacée renvoie en fait le résultat de l'exécution alloc
sur la sous-classe.
Je devrais commencer la réponse à condition que, bien que je l'ai testé dans divers scénarios et que je n'ai reçu aucune erreur, je ne peux pas garantir qu'il fera face à des configurations plus complexes (mais je ne vois aucune raison pour laquelle cela ne devrait pas fonctionner) . De plus, je n'ai soumis aucune application à l'aide de cette méthode, il y a donc une chance extérieure qu'elle soit rejetée par le processus de révision d'Apple (bien qu'une fois de plus je ne vois aucune raison pour laquelle cela devrait).
À des fins de démonstration, j'ai une sous-classe de UIViewController
called TestViewController
, qui a un IBOutlet UILabel et un IBAction. Dans mon storyboard, j'ai ajouté un contrôleur de vue et modifié sa classe en TestViewController
, et connecté l'IBOutlet à un UILabel et l'IBAction à un UIButton. Je présente le TestViewController au moyen d'un segment modal déclenché par un UIButton sur le viewController précédent.
Pour contrôler quelle classe est instanciée, j'ai ajouté une variable statique et des méthodes de classe associées afin d'obtenir / définir la sous-classe à utiliser (je suppose que l'on pourrait adopter d'autres façons de déterminer quelle sous-classe doit être instanciée):
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];
}
}
}
Pour mon test, j'ai deux sous-classes de TestViewController
: RedTestViewController
et GreenTestViewController
. Les sous-classes ont chacune des propriétés supplémentaires et chaque remplacement viewDidLoad
pour changer la couleur d'arrière-plan de la vue et mettre à jour le texte de l'IBOutlet UILabel:
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";
}
À certaines occasions, je pourrais vouloir s'instancier TestViewController
, à d'autres occasions RedTestViewController
ou GreenTestViewController
. Dans le contrôleur de vue précédent, je le fais au hasard comme suit:
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"];
}
Notez que la setClassForStoryBoard
méthode vérifie que le nom de classe demandé est bien une sous-classe de TestViewController, pour éviter toute confusion. La référence ci-dessus BlueTestViewController
est là pour tester cette fonctionnalité.