Có thể có bảng phân cảnh khởi tạo các lớp con khác nhau của bộ điều khiển chế độ xem tùy chỉnh, mặc dù nó liên quan đến một kỹ thuật hơi không chính thống: ghi đè alloc
phương thức cho bộ điều khiển chế độ xem. Khi bộ điều khiển chế độ xem tùy chỉnh được tạo, phương thức cấp phát ghi đè trên thực tế trả về kết quả của việc chạy alloc
trên lớp con.
Tôi nên mở đầu câu trả lời với điều kiện rằng, mặc dù tôi đã thử nghiệm nó trong nhiều tình huống khác nhau và không nhận được lỗi nào, tôi không thể đảm bảo rằng nó sẽ đối phó với các thiết lập phức tạp hơn (nhưng tôi không hiểu lý do gì nó không hoạt động) . Ngoài ra, tôi chưa gửi bất kỳ ứng dụng nào bằng cách sử dụng phương pháp này, vì vậy có khả năng bên ngoài là nó có thể bị từ chối bởi quy trình xem xét của Apple (mặc dù một lần nữa tôi không thấy lý do tại sao lại như vậy).
Đối với mục đích trình diễn, tôi có một lớp con của UIViewController
được gọi TestViewController
, lớp này có IBOutlet UILabel và IBAction. Trong bảng phân cảnh của mình, tôi đã thêm một bộ điều khiển chế độ xem và sửa đổi lớp của nó TestViewController
, đồng thời kết nối IBOutlet với UILabel và IBAction với UIButton. Tôi trình bày TestViewController theo cách của một segue phương thức được kích hoạt bởi UIButton trên viewController trước đó.
Để kiểm soát lớp nào được khởi tạo, tôi đã thêm một biến tĩnh và các phương thức lớp liên quan để lấy / đặt lớp con sẽ được sử dụng (tôi đoán người ta có thể áp dụng các cách khác để xác định lớp con nào sẽ được khởi tạo):
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];
}
}
}
Đối với bài kiểm tra của tôi, tôi có hai lớp con là TestViewController
: RedTestViewController
và GreenTestViewController
. Mỗi lớp con có các thuộc tính bổ sung và mỗi lớp ghi đè viewDidLoad
để thay đổi màu nền của dạng xem và cập nhật văn bản của 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";
}
Trong một số trường hợp, tôi có thể muốn khởi tạo TestViewController
chính nó, vào những dịp khác RedTestViewController
hoặc GreenTestViewController
. Trong bộ điều khiển chế độ xem trước, tôi thực hiện việc này một cách ngẫu nhiên như sau:
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"];
}
Lưu ý rằng setClassForStoryBoard
phương thức kiểm tra để đảm bảo rằng tên lớp được yêu cầu thực sự là một lớp con của TestViewController, để tránh bất kỳ sự trộn lẫn nào. Tham khảo ở trên BlueTestViewController
là có để kiểm tra chức năng này.