【问题标题】:When should I release objects in -(void)viewDidUnload rather than in -dealloc?我什么时候应该在 -(void)viewDidUnload 而不是 -dealloc 中释放对象?
【发布时间】:2010-11-12 15:03:47
【问题描述】:

-(void)viewDidUnload 有什么用处?

我能不能只发布-dealloc 中的所有内容?如果视图确实卸载了,-dealloc 不会被调用吗?

【问题讨论】:

    标签: iphone objective-c ios cocoa-touch memory-management


    【解决方案1】:

    作为documentation says

    当视图控制器需要释放其视图以及与该视图关联的任何对象以释放内存时,在内存不足的情况下调用它。

    在同样的情况下,dealloc被调用。此方法仅适用于 OS3 及以上版本。在 iPhone OS 2.x 中处理同样的情况真的很痛苦!

    2015 年 7 月更新:应该注意的是,viewDidUnload 在 iOS 6 中已被弃用,因为“在内存不足的情况下不再清除视图,因此永远不会调用此方法。”所以,现代的建议是不要担心它并使用dealloc

    【讨论】:

    • 也来自文档:“您应该只对以后可以轻松重新创建的对象执行此操作,无论是在您的 viewDidLoad 方法中还是从应用程序的其他部分。您不应该使用此方法来释放用户数据或任何其他无法轻易重新创建的信息”。我自己也有这个问题,谢谢!
    • 如果视图当前可见怎么办?由于内存不足警告而放弃它不是很糟糕吗? ;) 那么应用程序将只是空白。由于内存不足,我没有发布视图的目的。如果我没有看到视图,我总是释放整个控制器。虽然我有一个根视图控制器,它保持完整并管理它的子视图控制器的所有加载/卸载......
    • 不,如果你只是将一个视图换成另一个视图,你就不会使用它。想想你有一个带有 UINavigationController 的“堆栈”视图的情况。只有一个视图是可见的,如果您有内存警告,您可以释放所有不可见的视图。
    • 如何控制 viewDidUnload 在当前可见视图上不被调用,正如Thanks 所指出的那样?
    • viewDidUnload 不会在当前可见的视图上调用,只会在不可见的视图上调用。
    【解决方案2】:

    您可以释放您持有的任何子视图,例如您在 loadView 方法中保留的 UIImageView,或者更好的是该 UIImageView 上的图像。

    【讨论】:

      【解决方案3】:

      请记住,viewDidUnload 是视图控制器中的方法,而不是视图中的方法。 视图的 dealloc 方法将在视图卸载时被调用,但视图控制器的 dealloc 方法可能要稍后才能调用。

      如果您收到内存不足警告并且您的视图未显示(例如,大约在您使用 UIImagePickerController 让用户拍照时发生),您的视图将被卸载并且需要在之后重新加载那个。

      【讨论】:

      • 这是有道理的。如果我总是放弃整个视图控制器会发生什么?这就是我实际上所做的。在这种情况下,我不必处理太多 -viewDidUnload 问题,对吗?我从来没有遇到过只删除视图的情况,因为如果它不可见,我总是会删除整个控制器。
      • 好吧,请记住,如果您的视图正在显示,但您有一个像 ImagePicker 这样的全屏视图,即使您没有计划,您的视图也可能会被卸载成为。
      【解决方案4】:

      除了已经指出的内容之外,我还想详细说明-viewDidUnload 背后的逻辑。

      实现它的最重要原因之一是UIViewController 子类通常还包含对视图层次结构中各种子视图的拥有引用。例如,这些属性可以在从 nib 加载时通过IBOutlets 设置,或者以编程方式在-loadView 中设置。

      UIViewController 对子视图的额外所有权意味着即使将其视图从视图层次结构中移除并释放以节省内存,通过这子视图也被视图释放,它们实际上不会被释放,因为UIViewController 本身仍然包含对这些对象的未完成保留引用。释放这些对象的 UIViewController 额外所有权可确保它们也将被释放以释放内存。

      UIViewController 视图为re-loaded 时,您在此处释放的对象通常会重新创建并重新设置,无论是来自 Nib 还是通过 -loadView 的实现。

      另请注意,在调用此方法时,UIViewControllerview 属性为 nil

      【讨论】:

      【解决方案5】:

      结论:

      视图控制器有一个视图属性。通常,一个 nib 或一段代码会向该视图添加其他视图。这经常发生在 -viewDidLoad 方法中,如下所示:

      - (void)viewDidLoad {
          [super viewDidLoad];
          [self createManyViewsAndAddThemToSelfDotView];
      }
      

      此外,nib 文件可能会创建一个按钮并将其附加到视图控制器的视图中。

      在 iPhone OS 2.2 上,当从系统调用 -didReceiveMemoryWarning 时,您必须释放一些东西来释放内存。如果有意义,您可以释放整个视图控制器的视图。或者只是其中的大量消耗内存的内容。

      - (void)didReceiveMemoryWarning {
          [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
          // Release anything that's not essential, such as cached data
      }
      

      现在,在新的 OS 3.0 中,有一个 -viewDidUnload 方法,当视图因内存不足而被卸载时,系统会调用该方法(请纠正我:这个方法究竟是什么时候调用的?)

      -viewDidUnload 用于释放视图控制器本身和视图拥有的所有对象。原因:如果视图控制器持有对视图子视图的引用,即按钮,则被引用的子视图不会被释放,因为它们的保留计数> = 1。它们在-viewDidUnload中释放后,它们可以被释放凭记忆。

      【讨论】:

      • 记得在视图中确实卸载了 self.button = nil;,而不是 [button release];.
      【解决方案6】:

      这是因为您通常会将@property 设置为"(nonatomic, retain)",因此为您创建的设置器会释放当前对象,然后保留参数,即

      self.property = nil;
      

      ...按照以下方式做一些事情:

      [property release];
      property = [nil retain];
      

      因此,您是用一块石头杀死两只鸟:内存管理(释放现有对象)并将指针分配给 nil(因为向 nil 指针发送任何消息都将返回 nil)。

      希望对您有所帮助。

      【讨论】:

        【解决方案7】:

        如果视图控制器从导航控制器堆栈中弹出并且没有保留在其他任何地方,它将被释放,并且会调用 dealloc 而不是 viewDidUnload。你应该在dealloc中释放在loadView中创建的视图,但不必将变量设置为nil,因为调用dealloc后变量将不再存在。

        【讨论】:

          【解决方案8】:

          Apple 已弃用 viewWillUnload,现在您应该使用 didReceiveMemoryWarning 或 dealloc 来释放您的对象。

          在 iOS 6 中,viewWillUnload 和 viewDidUnload 方法 UIViewController 现在已弃用。如果您使用这些方法 要释放数据,请改用 didReceiveMemoryWarning 方法。你 也可以使用该方法释放对视图的引用 控制器的视图(如果它没有被使用)。你需要测试一下 执行此操作之前视图不在窗口中。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-11-09
            • 2011-01-22
            • 2011-03-14
            • 1970-01-01
            • 2011-09-10
            • 2011-04-05
            相关资源
            最近更新 更多