什么时候设置XIB插座属性? [英] When are XIB outlet properties set?

查看:153
本文介绍了什么时候设置XIB插座属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用xib文件实现继承。是的,有点奇怪,但是让我告诉你原因。

I'm trying to implement inheritance with xib files. Yes, a little strange, but let me tell you why.

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

I have a class, SLBaseViewController that many of my view controllers inherit from. When I want a child view controller I create it in the usual way:

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

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

This works fine. SLHomeViewController is an SLBaseViewController (which is a UIViewController).

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

I'm doing this because I have other view controllers that I want to inherit SLBaseViewController behavior. In my case, I have a navigation UI widget that is common across my app, so a SLSceneViewControll inherits from SLBaseViewController also and both SLHomeViewController and SLSceneViewController both get the custom nav widget behavior.

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

The custom nav widget also has position information that is common across SLBaseViewControllers. So I implemented a poor man's way of doing xib inheritance.

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

并且继承在initWithNibName中完成

and the inheritance is done in 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,它就什么都不做,阻止了无限循环。

If I create a SLHomeViewController is load the xib of a SLBaseViewController and then copies the interesting property from it. If initWithNibName detects it is loading a SLBaseViewController it just does nothing, preventing an infinite loop.

当然,问题是尚未设置插座属性。所以它只是复制nil。

The problem is, of course, that the outlet properties are not set yet. So it just copies nil.

那么什么时候设置这些插座属性?

So when are these outlet properties set?

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

Or - is there a better way to do what I'm trying to do? It all seemed rosy until I copy the properties by hand. That seems pretty brittle to me.

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

(Note, I'm fine with iOS6-only solutions.)

推荐答案

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

It happens because of UIViewController's the lazy initialization.

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

The view of UIViewController will be loaded only after some one call the view property.

这样:

controller.view

因此,在您的情况下,您只需拨打 controller.view 之前 self.navBarExtendedFPO = controller.navBarExtendedFPO;

So, in your case, you can just call controller.view before self.navBarExtendedFPO = controller.navBarExtendedFPO;

解释视图生命周期更清晰,有一个例子:

To explaining view life cycle more clear, there is an example:

SLBaseViewController中有重写方法, self.label 是模拟
在XIB文件中定义的 navBarExtendedFPO

there is overridden methods in your SLBaseViewController, self.label is analog of navBarExtendedFPO defined in XIB file

- (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的方法

and there is method that creates 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

这篇关于什么时候设置XIB插座属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆