在 viewDidLoad 之前调用 ViewController 上的自定义 init 方法

Posted

技术标签:

【中文标题】在 viewDidLoad 之前调用 ViewController 上的自定义 init 方法【英文标题】:Custom init method on ViewController to be called before viewDidLoad 【发布时间】:2013-06-28 13:33:10 【问题描述】:

我有一个自定义容器视图控制器,我从情节提要中实例化它,它有一堆方法可以修改我已经设置出口到情节提要的子视图的内容。

有很多方法可以实例化这个 ViewController,目前我必须确保,无论我如何实例化它,我要么显示它,显式调用 loadView,要么访问它的 .view 属性我开始做任何使用其插座的事情(因为在调用loadView 之前它们都是空指针)。

理想情况下,我想在我的ViewController 的单个初始化方法中调用loadView.view 来解决这个问题,而不是必须调用.view我从中初始化 ViewController 的一堆不同的地方。

UIViewController 类是否有指定的初始化程序?如果没有,我需要用我的自定义初始化逻辑修改哪些方法,以确保无论如何都会在我的 ViewController 初始化时调用它?

【问题讨论】:

UIViewController 文档明确指出永远不应该直接调用loadView @MartinR 是的,Xcode 的警告也明确指出,属性 getter 不应该用于副作用。尽管如此,如果您想在显示 ViewController 并导致 loadView 被调用之前通过插座进行子视图操作,您别无选择,只能使用这两种禁止的方法之一——除非我错过了另一种选择,在哪种情况请在此处提供:***.com/a/1935566/1709587 【参考方案1】:

awakeFromNib 似乎适合您的目的。来自文档:

在实例化过程中,存档中的每个对象都是 未归档,然后使用适合其类型的方法进行初始化。 符合NSCoding 协议的对象(包括所有 UIViewUIViewController) 的子类使用它们的初始化 initWithCoder: 方法。 ... 毕竟对象 已经实例化和初始化,nib加载代码 为所有这些重新建立出口和操作连接 对象。然后调用对象的awakeFromNib 方法。

【讨论】:

这里值得注意的是,在引用文档中所做的保证,即在调用 awakeFromNib 时设置出口变量,在 ViewController 从情节提要加载的情况下,而不是.nib。见***.com/questions/17400547/… 和***.com/questions/2723042/…【参考方案2】:

您可以覆盖这些以覆盖初始化情况:

- (id) initWithCoder:(NSCoder *)aDecoder

    self = [super initWithCoder:aDecoder];
    if(self)
    
        [self customInit];
    
    return self;


- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) 
        [self customInit];
    
    return self;


- (id)init
    
        self = [super init];
        if (self) 
            [self customInit];
        
        return self;
    

- (void) customInit

    //custom init code

但这不是一个好的做法,您应该在 viewDidLoad 中进行子视图操作。

【讨论】:

谢谢。实际上,我自己只是想通了这一点-在询问之前我可能应该做更多的研究-但是:1)我不打算在初始化程序中进行任何子视图操作;正如我解释的那样,我只想调用[self loadView] 以便加载子视图并且出口不为空。 2) 看来,当通过[Storyboard instantiateViewControllerWithIdentifier] 实例化 ViewController 时,在 initWithCoder 中调用 [self loadView] 会引发 NSInternalInconsistencyException。 -1,因为这不能处理我要求的用例。 @MarkAmery:这里真的有必要投反对票吗?您询问了指定的初始化程序并得到了答案。您不能期望foggzilla 创建一个测试项目来检查[self loadView] 是否在initWithCoder 中工作。 - 实际上,我现在犹豫是否要给出替代答案,因为如果它在您的用例中不起作用,您会否决它... @MartinR 我在问题中提供了用例。我当然认为foggzilla 无法预测我在尝试使用initWithCoder 时遇到的问题,如果我处于他的位置,我可能会给出与他完全相同的答案——我很感激他帮助。尽管如此,这不是目前所说的问题的正确答案,所以我必须 -1。 谢谢@MartinR,你永远不知道你什么时候会踩到蛋壳来回答 @foggzilla:您已经回答了他的主要问题“UIViewController 类是否有指定的初始化程序?”,所以我认为 “谢谢,您的回答是正确的,但事实证明这对我的情况没有帮助”就足够了。 - 但是没有人可以做...

以上是关于在 viewDidLoad 之前调用 ViewController 上的自定义 init 方法的主要内容,如果未能解决你的问题,请参考以下文章

在 didSelectRowAtIndexPath 之前调用 viewDidLoad

在 applicationDidFinishLaunching 之前调用 viewDidLoad

在 init 方法完成之前调用 UIViewController viewDidLoad

是否有任何情况可以导致在 didBecomeActive 之前调用 ViewDidLoad?

在 viewDidLoad 之前调用 ViewController 上的自定义 init 方法

UIViewController 的子类在调用 super 之前可以在 viewDidLoad 中进行一些初始化吗?