【问题标题】:On iOS, if a view controller has no view yet, why does NSLog(@"self.view is %p", self.view) crash?在 iOS 上,如果视图控制器还没有视图,为什么 NSLog(@"self.view is %p", self.view) 会崩溃?
【发布时间】:2012-05-24 19:32:57
【问题描述】:

如果在 Xcode 4.3.2 和 AppDelegate.m 中使用 Empty App 模板创建新的 iOS 项目:

self.window.rootViewController = [[FooViewController alloc] init];

FooViewControllerviewDidLoad 中,如下:

NSLog(@"self.view is %p", self.view);
NSLog(@"self.view is %@", self.view);

将打印出视图,因此看起来默认的loadView 将实例化一个视图并将其分配给self.view

因此,如果我用一个全空的方法覆盖loadView,并注释掉上面的第二个NSLog 语句,我希望第一个NSLog 语句打印出0x0,但应用程序由于错误而崩溃NSLog 行的内存访问权限。为什么会这样?

【问题讨论】:

    标签: iphone ios uiview uiviewcontroller


    【解决方案1】:

    好的,在一个下意识的、明显错误的答案之后,我尝试了这个。 Empty App 模板没有 rootViewController,所以我使用了单个屏幕模板。运行后,我看到您遇到了堆栈溢出。在尝试访问 self.view 时,您正在调用超类上的 view 属性,然后它试图加载视图以返回它,据我所知,它正在调用 viewDidLoad 等。另一个 NSLog 语句也是如此。

    【讨论】:

    • 是的,就是这样。我错过了溢出...我正在删除我的答案。
    • 感谢您的洞察力。当self.view被访问时...我以为只是返回view实例变量?既然view 是由@property(nonatomic,retain) UIView *view; 定义的,那它不是只是一个实例变量吗?如果是这种情况,那么@synthesize 制作的访问器应该只返回实例变量......你提到超类试图“加载视图”......它如何尝试加载视图(从哪里?)当视图为零?
    • 查看 Shaggy Frog 的更好答案:当视图不在内存中时,通过访问视图属性触发加载循环。 viewDidLoad 是该循环的一部分,因此在没有视图时访问它会导致递归。
    【解决方案2】:

    view property in UIViewController 的文档指出:

    由于访问该属性会导致视图自动加载,可以使用isViewLoaded方法判断视图当前是否在内存中。

    它还有一个指向The View Controller Life Cycle 的链接,其中指出:

    加载周期中发生的步骤如下:

    1. 当视图控制器的view属性被访问并且视图当前不在内存中时触发加载循环。

    2. 视图控制器调用它的loadView 方法。 loadView 方法的默认实现做了以下两件事之一:

      • 如果视图控制器与情节提要相关联,它会从情节提要中加载视图。

      • 如果视图控制器未与情节提要相关联,则会创建一个空的 UIView 对象并将其分配给 view 属性。

    3. 视图控制器调用其viewDidLoad 方法以允许您的子类执行任何额外的加载时任务。

    所以当你说:

    所以如果我用一个全空的方法覆盖loadView

    您故意破坏生命周期,因为当您覆盖的loadView 版本完成时,它应该已经加载了一个视图。因为它没有,所以你会崩溃。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-25
      • 2011-09-08
      • 1970-01-01
      • 2012-03-28
      • 2012-03-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多