在 initWithNibName:bundle 期间创建一次性变量时未设置 IBOutlets: [英] IBOutlets not being set EXCEPT when creating throwaway variables during initWithNibName:bundle:

查看:30
本文介绍了在 initWithNibName:bundle 期间创建一次性变量时未设置 IBOutlets:的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先让我说我已经搜索过谷歌,虽然很多人都有类似的问题,但我没有看到以下奇怪的行为和补救措施.

我已经创建了一个 UIViewController 并将笔尖与几个 IBOutlets 相关联.在尝试从另一个类使用这个笔尖时,我发现在使用 initWithNibName:bundle: 实例化它之后,IBOutlets 仍然为零.

我确认它们连接正确,是的,它们正在合成,但仍然没有.在进一步调查时,我将 initWithNibName 方法更改如下:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];如果(自我){UIView *view = self.view;NSArray *subviews = self.view.subviews;NSLog(@"加载的视图包含 %d 个子视图.", [子视图计数]);}回归自我;}

令人难以置信的是,这里添加了三行,创建一次性变量和日志记录,使 IBOutlets 正确连接并从外部工作.

我已经清理并重建并重新启动了我的机器,但是,如果我删除这些行,它仍然会停止工作.我在这里真的很困惑,担心我有某种巫术在我发货的那一刻就会坏掉.对可能发生的事情有什么想法吗?

解决方案

您误解了 initWithNibName:bundle: 的作用,以及 UIViewController 何时加载其笔尖.

initWithNibName:bundle: 方法记录要加载的笔尖名称.它不会立即加载笔尖.

-[UIViewController view] 方法按需加载笔尖,必要时通过发送[self loadView].-[UIViewController view] 的实现基本上是这样的:

- (UIView *)view {如果(_view == nil){[自加载视图];[self viewDidLoad];}返回_视图;}

因此,如果您在 initWithNibName:bundle: 覆盖中调用 self.view,那导致视图控制器加载其笔尖.

然而,从 initWithNibName:bundle: 调用 self.view 通常是不合适的.视图控制器应该能够在没有视图层次结构的情况下存在.

例如,假设用户正在运行您的应用并浏览多个视图控制器,您通过将视图控制器推送到导航控制器上来实现.然后用户切换到另一个应用程序一段时间.现在系统内存不足,因此它会杀死后台应用程序 - 包括您的应用程序.

当用户再次启动您的应用时,您的应用(如果做得好)应该尝试恢复用户的状态.这意味着使用推送视图控制器堆栈重新加载导航控制器.但只有顶视图控制器的视图在屏幕上可见.立即重新加载所有隐藏视图控制器的视图会浪费时间、内存和电池.这就是每个视图控制器按需加载其笔尖的原因.

Let me first say that I've searched Google and, although many have similar issues, I haven't seen anything with the following bizarre behavior and remedy.

I've created a UIViewController and associated nib with several IBOutlets. On trying to consume this nib from another class, I discovered that after instantiating it with initWithNibName:bundle:, the IBOutlets are still nil.

I confirmed that they are correctly wired up, and yes, they are being synthesized, but still nothing. While investigating further, I changed the initWithNibName method as follows:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {

        UIView *view = self.view;
        NSArray *subviews = self.view.subviews;
        NSLog(@"Loaded view containing %d subviews.", [subviews count]);

    }
    return self;
}

Unbelievably, the addition of the three lines here, creating throwaway variables and logging, makes the IBOutlets wire up properly and work from the outside.

I have cleaned and rebuilt and restarted my machine, but still, if I remove these lines, it stops working. I am really baffled here and concerned that I have some kind of voodoo working that's going to break the moment I ship. Any ideas on what could be happening?

解决方案

You misunderstand what initWithNibName:bundle: does, and when a UIViewController loads its nib.

The initWithNibName:bundle: method records the name of the nib to be loaded. It does not immediately load the nib.

The -[UIViewController view] method loads the nib on demand, by sending [self loadView] if necessary. The implementation of -[UIViewController view] is basically this:

- (UIView *)view {
    if (_view == nil) {
        [self loadView];
        [self viewDidLoad];
    }
    return _view;
}

So if you call self.view in your initWithNibName:bundle: override, that will cause the view controller to load its nib.

However, it's generally inappropriate to call self.view from initWithNibName:bundle:. A view controller should be able to exist without its view hierarchy.

For example, suppose a user is running your app and navigates through several view controllers, which you implement by pushing the view controllers onto a navigation controller. Then the user switches to another app for a while. Now the system is running low on memory, so it kills background apps - including your app.

When the user launches your app again, your app (if it's well done) should try to restore the user's state. That means reloading the navigation controller with the stack of push view controllers. But only the top view controller's view is visible on screen. It would be a waste of time, memory, and battery to reload the views for all of the hidden view controllers immediately. That's why each view controller loads its nib on demand.

这篇关于在 initWithNibName:bundle 期间创建一次性变量时未设置 IBOutlets:的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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