情节提要可能会实例化自定义视图控制器的不同子类,尽管它涉及一种稍微不合常规的技术:覆盖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
和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
用来测试此功能。