Il est possible d'avoir un storyboard instancier différentes sous-classes d'un contrôleur de vue personnalisé, bien que cela implique une technique légèrement non orthodoxe: en remplaçant la méthode alloc
pour le contrôleur de vue. Lorsque le contrôleur de vue personnalisé est créé, la méthode alloc remplacée renvoie en fait le résultat de l'exécution de alloc
sur la sous-classe.
Je devrais prévenir la réponse en spécifiant que, bien que je l'ai testée dans divers scénarios et n'ai reçu aucune erreur, je ne peux pas garantir qu'elle fonctionnera avec 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 utilisant cette méthode, donc il y a une chance qu'elle puisse être rejetée par le processus de révision d'Apple (encore une fois, je ne vois aucune raison pour laquelle cela devrait arriver).
À des fins de démonstration, j'ai une sous-classe de UIViewController
appelée TestViewController
, qui a un IBOutlet UILabel, et une IBAction. Dans mon storyboard, j'ai ajouté un contrôleur de vue et modifié sa classe en TestViewController
, et j'ai connecté l'IBOutlet à un UILabel et l'IBAction à un UIButton. Je présente le TestViewController via un segue modal déclenché par un UIButton sur le contrôleur de vue 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 pour obtenir/définir la sous-classe à utiliser (je suppose qu'on pourrait adopter d'autres moyens 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(@"Attention : %@ n'est pas une sous-classe de %@, on revient à la classe de base", 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 override 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 = "Défini par RedTestVC";
}
GreenTestViewController.m:
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor greenColor];
self.testLabel.text = "Défini par GreenTestVC";
}
À certaines occasions, je pourrais vouloir instancier TestViewController
lui-même, à d'autres occasions RedTestViewController
ou GreenTestViewController
. Dans le contrôleur de vue précédent, je le fais au hasard de la manière suivante :
NSInteger vcIndex = arc4random_uniform(4);
if (vcIndex == 0) {
NSLog(@"Choisi TestVC");
[TestViewController setClassForStoryBoard:@"TestViewController"];
} else if (vcIndex == 1) {
NSLog(@"Choisi RedVC");
[TestViewController setClassForStoryBoard:@"RedTestViewController"];
} else if (vcIndex == 2) {
NSLog(@"Choisi BlueVC");
[TestViewController setClassForStoryBoard:@"BlueTestViewController"];
} else {
NSLog(@"Choisi GreenVC");
[TestViewController setClassForStoryBoard:@"GreenTestViewController"];
}
Remarquez que la méthode setClassForStoryBoard
vérifie pour s'assurer que le nom de classe demandé est en effet une sous-classe de TestViewController, pour éviter toute confusion. La référence ci-dessus à BlueTestViewController
est là pour tester cette fonctionnalité.
3 votes
Il pourrait être utile de mentionner que vous pouvez le faire avec Nib. Mais si vous êtes comme moi et que vous voulez certaines fonctionnalités intéressantes que seul le storyboard a (cellule statique/prototype, par exemple), alors je suppose que nous n'avons pas de chance.
0 votes
stackoverflow.com/questions/27336730/…
0 votes
Est-ce que cela répond à votre question? Jeter à une sous-classe depuis Storyboard
0 votes
Il y a 10 ans, c'est maintenant trivial stackoverflow.com/a/76772592/294884