Storyboard dapat membuat instance subclass berbeda dari pengontrol tampilan kustom, meskipun ini melibatkan teknik yang sedikit tidak ortodoks: mengganti alloc
metode untuk pengontrol tampilan. Saat pengontrol tampilan kustom dibuat, metode alokasi yang diganti sebenarnya mengembalikan hasil dari berjalan alloc
pada subkelas.
Saya harus mengawali jawaban dengan syarat bahwa, meskipun saya telah mengujinya dalam berbagai skenario dan tidak menerima kesalahan, saya tidak dapat memastikan bahwa itu akan mengatasi pengaturan yang lebih kompleks (tetapi saya tidak melihat alasan mengapa tidak berfungsi) . Juga, saya belum mengirimkan aplikasi apa pun menggunakan metode ini, jadi ada kemungkinan luar bahwa itu mungkin ditolak oleh proses peninjauan Apple (meski sekali lagi saya tidak melihat alasan mengapa harus).
Untuk tujuan demonstrasi, saya memiliki subkelas yang UIViewController
disebut TestViewController
, yang memiliki IBOutlet UILabel, dan IBAction. Di storyboard saya, saya telah menambahkan pengontrol tampilan dan mengubah kelasnya menjadi TestViewController
, dan menghubungkan IBOutlet ke UILabel dan IBAction ke UIButton. Saya menyajikan TestViewController melalui segue modal yang dipicu oleh UIButton pada viewController sebelumnya.
Untuk mengontrol kelas mana yang dipakai, saya telah menambahkan variabel statis dan metode kelas terkait jadi dapatkan / setel subkelas yang akan digunakan (saya kira seseorang dapat mengadopsi cara lain untuk menentukan subkelas mana yang akan dipakai):
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];
}
}
}
Untuk pengujian saya, saya memiliki dua subclass dari TestViewController
: RedTestViewController
dan GreenTestViewController
. Masing-masing subclass memiliki properti tambahan dan masing-masing mengganti viewDidLoad
untuk mengubah warna latar belakang tampilan dan memperbarui teks 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";
}
Pada beberapa kesempatan saya mungkin ingin membuat contoh TestViewController
sendiri, pada kesempatan lain RedTestViewController
atau GreenTestViewController
. Di pengontrol tampilan sebelumnya, saya melakukan ini secara acak sebagai berikut:
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"];
}
Perhatikan bahwa setClassForStoryBoard
metode ini memeriksa untuk memastikan bahwa nama kelas yang diminta memang merupakan subkelas TestViewController, untuk menghindari campur-aduk. Referensi di atas BlueTestViewController
untuk menguji fungsionalitas ini.