ストーリーボードにカスタムビューコントローラーのさまざまなサブクラスをインスタンス化させることは可能ですが、これには少し変わったalloc
手法、つまりビューコントローラーのメソッドをオーバーライドすることが含まれます。カスタムビューコントローラーが作成されると、オーバーライドされたallocメソッドは、実際alloc
にはサブクラスで実行した結果を返します。
さまざまなシナリオでテストしてエラーが発生しなかったとしても、より複雑な設定に対応できるかどうかは保証できません(ただし、機能しない理由はわかりません)。 。また、私はこの方法を使用してアプリを提出していないため、Appleのレビュープロセスで拒否される可能性があります(ただし、なぜそうする必要があるのかはわかりません)。
デモンストレーションの目的のために、私が持っているのサブクラスUIViewController
と呼ばれるTestViewController
UILabel IBOutletとIBActionを持っています、。私のストーリーボードでは、ビューコントローラーを追加してそのクラスをTestViewController
に修正し、IBOutletをUILabelに、IBActionをUIButtonにフックしています。前のviewControllerのUIButtonによってトリガーされるモーダルセグエを使用してTestViewControllerを提示します。
インスタンス化するクラスを制御するために、使用するサブクラスを取得/設定するように、静的変数と関連するクラスメソッドを追加しました(インスタンス化するサブクラスを決定する他の方法を採用できると思います)。
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];
}
}
}
私のテストでは、TestViewController
:RedTestViewController
との2つのサブクラスがありGreenTestViewController
ます。サブクラスにはそれぞれ追加のプロパティがあり、それぞれオーバーライドviewDidLoad
してビューの背景色を変更し、UILabel IBOutletのテキストを更新します。
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";
}
場合によってはTestViewController
、自分自身をインスタンス化したい場合もあれば、それ以外の場合RedTestViewController
もありGreenTestViewController
ます。前のビューコントローラでは、次のようにランダムにこれを行います。
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"];
}
このsetClassForStoryBoard
メソッドは、要求されたクラス名が実際にTestViewControllerのサブクラスであることを確認して、混乱を避けることに注意してください。上記の参照BlueTestViewController
は、この機能をテストするためのものです。