在视图控制器中,您在哪里初始化属性值?

6
我有一个视图控制器,其行为由属性决定。这些属性在其父级中通过prepareForSegue进行设置。
这可能会导致我的程序出现潜在的错误,因为不能保证设置属性的父级已经设置好了这些属性,所以我想要有一个默认值。经过研究,我现在明白Objective C中的属性没有默认值。这让我只剩下以下选择:
  • 在子视图的viewDidLoad方法中设置属性的默认值。然而,在调查后发现,viewDidLoad在父级中的prepareForSegue之后调用,因此当父级实际上设置属性时,我将覆盖父级的值。
  • 然后我想使用(id)init来初始化这些值,但至少在使用storyboards时,这个方法根本不被调用!
我可能有一个解决办法,即对象将初始化为默认值,但在这种情况下,我只想传递一个BOOL值。由于即使未正确初始化,bool也会有一些值,所以我无法测试它是否为非空。
在父级的prepareForSegue之前,是否有任何机会在子视图控制器中初始化值?
1个回答

7
覆盖 init 方法是无效的,因为它不是 UIViewController 对象的指定初始化器。当手动实例化视图控制器时,会调用 - (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle 方法,在从故事板中加载时,将调用 - (id)initWithCoder:(NSCoder *)decoder 方法。如果您想在视图控制器初始化时设置属性,则必须重写这两个初始化器。

经过研究,我现在明白了 Objective C 中的属性没有默认值。

实际上有默认值。对于对象来说是 nil,对于整数值是 0,对于浮点数是 0.0 等等。如果您需要除此之外的默认值,则应在适当的初始化方法中设置它们。


你必须同时覆盖这两个方法吗?这可能是我迄今在Objective C中看到的最笨重的事情。很遗憾,没有像 viewDidLoad 这样的钩子函数,可以让外部操作者在发送消息给你的视图控制器之前先执行它。 - El Tea
1
覆盖两者都是非常不寻常的。大多数对象要么来自storyboard,要么不是。如果它们来自storyboard,则覆盖initWithCoder:(或awakeFromNib)就足够了。如果您正在编写一个极其可重用的代码片段,则创建一个可以从两个初始化路径调用的-setup方法并不罕见。但在许多情况下,仔细选择属性含义可以使默认值起作用(0、NO、nil等),因此您无需初始化它们。实际上,我发现这种情况并不经常出现。 - Rob Napier
那么也许我没有理解 - 我是需要覆盖一个还是两个才能实现我在初始化器方面寻找的东西? - El Tea
@Rob - 先前已删除的答案中有一条评论也很有帮助。我没有意识到BOOL保证被初始化为0,是的,有了这个信息我可以做到我想要的效果。我的后续问题是关于只初始化一个还是两个,更多地是为了理解iOS的这个部分是如何工作的。 - El Tea
2
如果您想要能够从storyboards和手动分配中使用视图控制器,则必须同时覆盖两者。如果您只使用storyboards,覆盖initWithCoder:就足够了。 - Sebastian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接