什么时候设置XIBsockets属性?

我正在尝试使用xib文件实现inheritance。 是的,有点奇怪,但让我告诉你为什么。

我有一个类,我的许多视图控制器inheritance的SLBaseViewController。 当我想要一个子视图控制器时,我会以通常的方式创建它:

SLHomeViewController *controller = [[SLHomeViewController alloc] initWithNibName:@"SLHomeViewController" bundle:nil]; 

这很好用。 SLHomeViewController是一个SLBaseViewController(它是一个UIViewController)。

我这样做是因为我有其他视图控制器,我想inheritanceSLBaseViewController行为。 在我的例子中,我有一个在我的应用程序中常见的导航UI小部件,因此SLSceneViewControll也从SLBaseViewControllerinheritance,并且SLHomeViewController和SLSceneViewController都获得自定义导航小部件行为。

自定义导航窗口小部件还具有在SLBaseViewControllers中通用的位置信息。 所以我实现了一个穷人做xibinheritance的方法。

 @interface SLBaseViewController : UIViewController  @property (strong, nonatomic) IBOutlet UIView *navBarExtendedFPO; 

并且inheritance在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; } 

如果我创建一个SLHomeViewController,则加载SLBaseViewController的xib,然后从中复制有趣的属性。 如果initWithNibName检测到它正在加载SLBaseViewController,它就什么也不做,阻止了无限循环。

当然,问题是出口属性尚未设定。 所以它只是复制零。

那么这些出口属性何时设定?

或者 – 有没有更好的方法来做我想做的事情? 在我手工复制属性之前,这一切看起来都很美好。 这对我来说似乎很脆弱。

(注意,我只使用iOS6解决方案。)

这是因为UIViewController的延迟初始化。

只有在调用view属性之后才会加载UIViewController的视图。

像那样:

 controller.view 

因此,在您的情况下,您可以在self.navBarExtendedFPO = controller.navBarExtendedFPO;之前调用self.navBarExtendedFPO = controller.navBarExtendedFPO;

为了更清楚地解释视图生命周期,有一个例子:

在SLBaseViewController中有重写的方法, self.label navBarExtendedFPO XIB文件中定义的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); } 

并且有创建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); 

所以,有我们的日志:

 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