我正在尝试使用xib文件实现继承.是的,有点奇怪,但让我告诉你为什么.
我有一个类,SLBaseViewController,我的许多视图控制器继承.当我想要一个子视图控制器时,我会以通常的方式创建它:
SLHomeViewController *controller = [[SLHomeViewController alloc] initWithNibName:@"SLHomeViewController" bundle:nil];
Run Code Online (Sandbox Code Playgroud)
这很好用.SLHomeViewController是一个SLBaseViewController(它是一个UIViewController).
我这样做是因为我有其他视图控制器,我想继承SLBaseViewController行为.在我的例子中,我有一个在我的应用程序中常见的导航UI小部件,因此SLSceneViewControll也从SLBaseViewController继承,并且SLHomeViewController和SLSceneViewController都获得自定义导航小部件行为.
自定义导航窗口小部件还具有在SLBaseViewControllers中通用的位置信息.所以我实现了一个穷人做xib继承的方法.
@interface SLBaseViewController : UIViewController <SLNavBarViewControllerDelegate>
@property (strong, nonatomic) IBOutlet UIView *navBarExtendedFPO;
Run Code Online (Sandbox Code Playgroud)
并且继承在initWithNibName中完成
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
Class callingClass = [self class];
Class slBaseViewControllerClass = NSClassFromString (SL_BASE_VC_CLASS_NAME);
if (callingClass != slBaseViewControllerClass) {
SLBaseViewController *controller = [[SLBaseViewController alloc] initWithNibName:@"SLBaseViewController" bundle:nil];
// now load all the properties by hand
self.navBarExtendedFPO = controller.navBarExtendedFPO;
}
}
return self;
}
Run Code Online (Sandbox Code Playgroud)
如果我创建一个SLHomeViewController,则加载SLBaseViewController的xib,然后从中复制有趣的属性.如果initWithNibName检测到它正在加载SLBaseViewController,它就什么也不做,阻止了无限循环.
当然,问题是出口属性尚未设定.所以它只是复制零.
那么这些出口属性何时设定?
或者 - 有没有更好的方法来做我想做的事情?在我手工复制属性之前,这一切看起来都很美好.这对我来说似乎很脆弱.
(注意,我只使用iOS6解决方案.)
这是因为UIViewController的延迟初始化.
只有在调用view属性之后才会加载UIViewController的视图.
像那样:
controller.view
Run Code Online (Sandbox Code Playgroud)
所以,在你的情况下,你可以controller.view先打电话self.navBarExtendedFPO = controller.navBarExtendedFPO;
为了更清楚地解释视图生命周期,有一个例子:
SLBaseViewController中有重写的方法,类似于XIB文件self.label中navBarExtendedFPO定义的方法
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
NSLog(@"initWithNibName: view loaded - %d , IBOuttlet loaded - %d", [self isViewLoaded], self.label != nil);
}
return self;
}
- (void)loadView {
NSLog(@"loadView1: view loaded - %d , IBOuttlet loaded - %d", [self isViewLoaded], self.label != nil);
[super loadView];
NSLog(@"loadView2: view loaded - %d , IBOuttlet loaded - %d", [self isViewLoaded], self.label != nil);
}
- (void)viewDidLoad
{
NSLog(@"viewDidLoad1: view loaded - %d , IBOuttlet loaded - %d", [self isViewLoaded], self.label != nil);
[super viewDidLoad];
NSLog(@"viewDidLoad2: view loaded - %d , IBOuttlet loaded - %d", [self isViewLoaded], self.label != nil);
}
Run Code Online (Sandbox Code Playgroud)
并且有创建SLBaseViewController的方法
SLBaseViewController *testController = [[SLBaseViewController alloc] initWithNibName:@"SLBaseViewController" bundle:nil];
NSLog(@"after initialization: view loaded - %d , IBOuttlet loaded - %d", [testController isViewLoaded], testController.label != nil);
UIView * testView = testController.view;
NSLog(@"after calling testView.view: view loaded - %d , IBOuttlet loaded - %d", [testController isViewLoaded], testController.label != nil);
Run Code Online (Sandbox Code Playgroud)
所以,有我们的日志:
initWithNibName: view loaded - 0 , IBOuttlet loaded - 0
after initialization: view loaded - 0 , IBOuttlet loaded - 0
loadView1: view loaded - 0 , IBOuttlet loaded - 0
loadView2: view loaded - 1 , IBOuttlet loaded - 1
viewDidLoad1: view loaded - 1 , IBOuttlet loaded - 1
viewDidLoad2: view loaded - 1 , IBOuttlet loaded - 1
after calling testView.view: view loaded - 1 , IBOuttlet loaded - 1
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1458 次 |
| 最近记录: |