【问题标题】:iOS 6 - viewDidUnload migrate to didReceiveMemoryWarning?iOS 6 - viewDidUnload 迁移到 didReceiveMemoryWarning?
【发布时间】:2012-09-22 08:39:35
【问题描述】:

那么,viewDidUnload 自 iOS 6 起已弃用,我现在需要做什么?

删除它,将didReceiveMemoryWarning中的所有内容迁移出去,或者离开它,在didReceiveMemoryWarning中不做任何事情?

【问题讨论】:

    标签: ios


    【解决方案1】:

    简短的回答是,在许多情况下,您不需要更改任何内容。而且,您肯定想简单地将viewDidUnload 的所有内容迁移到didReceiveMemoryWarning

    一般来说,我们大多数人都会在viewDidUnload 中设置IBOutletnil 的引用(主要是因为Interface Builder 会为我们设置)并进行一般的内存释放(例如清除缓存、释放didReceiveMemoryWarning 中易于重新创建的模型数据等)。如果您是这样做的,那么您可能不需要任何代码更改。

    根据 iOS 6 viewDidUnload 文档:

    在内存不足的情况下不再清除视图,因此永远不会调用此方法。

    因此,您确实想将IBOutletnil 的引用设置移动到任何地方,因为不再清除视图。在didReceiveMemoryWarning 中将它们设置为nil 或类似的东西是没有意义的。

    但是,如果您通过在viewDidUnload 中释放易于重新创建的模型对象、清空缓存等来响应低内存事件,那么这些东西肯定应该移至didReceiveMemoryWarning。但话说回来,我们大多数人已经有了它。

    最后,如果你释放 didReceiveMemoryWarning 中的任何东西,只要确保你的代码在你弹回时不依赖于它们在 viewDidLoad 中重新创建,因为它不会被调用(因为视图本身,从未卸载过)。

    正如 applefreak 所说,这取决于您在 viewDidUnload 中所做的事情。如果您用viewDidUnload 中的明确示例更新您的问题,我们可能会提供不那么抽象的建议。

    【讨论】:

      【解决方案2】:

      简短回答:

      永远不要使用 -didReceiveMemoryWarning 进行平衡拆除,因为它可能永远不会或多次调用。如果您在 -viewDidLoad 中进行了设置,请将清理代码放在 -dealloc 中。


      长答案:

      要给出一个笼统的答案并不容易,因为这确实取决于具体情况。但是,有两个重要的事实需要说明:

      1. -viewDidUnload 已被弃用,实际上从 iOS6 及更高版本开始从未调用过。所以,如果你有你的清理代码,你的应用会在这些操作系统版本下泄漏

      2。 -didReceiveMemoryWarning 可能会被调用多次或从不调用。因此,对于您在其他地方创建的对象进行平衡拆卸来说,这是一个非常糟糕的地方

      我的答案是查看您使用属性的常见情况,例如:

      @property (strong) UIView *myCustomView  // <-- this is what I'm talking about
      @property (assign) id *myDelegate
      

      在这里您必须进行一些清理,因为您创建并拥有 customView 或 InterfaceBuilder 创建了它,但您保留了它。在 iOS 6 之前,您可能会这样做:

      - (void)viewDidLoad {
          self.myCustomView = [[UIView alloc] initWithFrame:…];
      }
      - (void)viewDidUnload {  // <-- deprecated!
          [myCustomView removeFromSuperView];
          self.myCustomView = nil;
      }
      

      ...因为(再次)myCustomView 是保留财产,由您创建和拥有,因此您必须小心并在最后“释放”它(将其设置为 nil)。

      在 iOS 6 中,替换 -viewDidUnload 并将保留属性设置为 nil 的最佳位置可能是 -dealloc。还有viewWillAppearviewDidDisappear,但这些与视图/控制器的生命周期无关,而是显示周期(另一方面,-...appear 方法非常适合取消/注册通知侦听器!)。因此,在每次显示之前和之后创建和销毁视图可能并不合适。 dealloc 是我们唯一可以确定在控制器生命周期结束时调用的方法。请注意,如果您使用 ARC,则不得致电 [super dealloc]

      - (void)dealloc {
          self.myCustomView = nil;
      }
      

      但是,如果您使用viewDidLoad 进行一些可以在内存不足的情况下释放的视图相关设置,那么其他显示如何处理内存不足情况的帖子是完全有效的。在这种情况下,您也可以使用 dealloc,但您必须检查您的视图是否仍然存在。

      ViewController 的生命周期

      也许查看 ViewController 的一般生命周期也很有帮助:

      这是视图控制器的生命周期(斜体表示这些方法可能会被多次调用)

      • init:ViewController 已加载,尚无可用的界面元素 (IBOutlet)(全部为零)
      • viewDidLoad:nib/storyboard 已经加载,所有对象都可用。用户什么都看不到
      • viewWillAppear:即将显示视图
      • viewDidAppear:视图在屏幕上
      • viewWillDisappear:视图即将消失
      • viewDidDisappear:视图刚刚从窗口中移除
      • viewDidUnload:在 iOS6/7 中从不调用
      • didReceiveMemoryWarning:您不知道是否、何时以及多久调用一次。在 iOS6 之前它可能会卸载视图,在 iOS6 之后它只是清除屏幕外缓存或什么都不做
      • dealloc:viewController 即将被销毁

      所以,总而言之,有多种可能性;现在去哪里真的取决于在哪里初始化了什么:

      • -dealloc 如果在 -init: 或 -viewDidLoad: 中创建
      • -viewWill/DidDisappear(与-viewWill/DidAppear 配对)
      • -didReceiveMemoryWarning(可能会或可能不会被调用)

      【讨论】:

      • +1 好答案。顺便说一句,对于 iOS 7 动态转换,viewWillAppear 可能更好地描述为“视图将(或可能)显示”,viewWillDisappear 最好描述为“视图将(或可能)被删除”。对于动态转换,我们不再保证viewWillAppear 后面会跟着viewDidAppear,也不能保证viewWillDisappear 后面会跟着viewDidDisappear
      • 另外,在您的myCustomView 示例中,我希望没有人这样做,因为这只是解决方案的一半:即使在iOS 5 中,他们也必须在@ 中执行release 的东西987654340@ 也是,因为 viewDidUnload 从未被称为“最后”,而只是在您推送/呈现另一个视图的内存压力下。 viewDidUnload 在您刚刚关闭控制器时从未被调用,仅在内存压力情况下。因此,他们不会将 releasemyCustomView 转移到 dealloc,而是无论如何它都需要在那里。
      • dealloc 不会在任何对象(例如某种通知程序)持有对此 viewController 的强引用时被调用!
      【解决方案3】:

      如果您需要知道您的 UIViewController 是否正在关闭,您可以将此代码添加到您的 viewWillDisappear:

      - (void)viewWillDisappear:(BOOL)animated
      {
          [super viewWillDisappear:animated];
      
          if ([self isBeingDismissed] || [self isMovingFromParentViewController])
          {
              // Do your viewDidUnload stuff
          }
      }
      

      它不会与 viewDidUnload 在视图控制器生命周期中同时调用一次,但在大多数情况下可以满足您的需求!

      【讨论】:

        【解决方案4】:

        取决于您在viewDidUnload 中所做的事情,但您可以使用didReceiveMemoryWarningdealloc 来发布数据。见this

        【讨论】:

        • 我同意这仅取决于 Devfly 的 viewDidUnload 中的内容,但如果由于 iOS 6 有任何需要移动到 dealloc 的内容,我会感到震惊。通常,当我们使用一个视图控制器,然后关闭/弹出它,viewDidUnload 永远不会被调用(它只在内存不足的情况下使用),所以希望viewDidUnload 中没有例行清理,他们也不会在dealloc 中清理!如果有人用viewDidUnload 代替dealloc 做这种事情,那么他们手上的问题就更大了。
        • 你是对的 Rob。我认为您使用 dealloc 来删除观察者?我知道 iOS 6.0 会在视图控制器被卸载后自动释放它的内存映像,但如果我想在视图控制器释放之前执行一些操作。例如调用通信管理器的取消订阅方法,使其观察者计数减一。所以我在 iOS 6.0 中所做的是,在 intiWithCoder 中订阅观察者并在 dealloc 中取消订阅。这是糟糕的设计吗?
        • 这一切都与这篇文章无关,但在你引用的其他讨论中,OP 显然不明白viewDidUnload 的目的。但是在回答您的问题时,是的,您可以在dealloc 中提供此类内容,但viewWillDisappear 可能更好。最重要的是,如果您的通信管理器保持对您的视图控制器的强引用,那么您绝对不应该尝试取消订阅dealloc(因为您将有一个强引用循环;dealloc 将永远不会被调用)。这类事情必须在其他地方完成,例如viewWillDisappear.
        • 谢谢@Rob。你是对的,但是你必须在 dealloc 中做一些事情。我不能在 viewWillDisappear 或 viewDidDisappear 中做,因为该视图呈现另一个视图!在任何时候,我都不想退订中级孩子!在使用带有 segue 类型“Modal”的情节提要时,当您呈现另一个视图控制器时,您会得到视图消失消息,但当视图实际上从内存中删除时,您只会得到一次 dealloc。我有另一种在 viewWillAppear/ViewWillDisapper 中订阅/取消订阅的方法,但我希望我的视图控制器从通讯管理器接收消息,直到它在内存中!
        【解决方案5】:

        在大多数典型情况下,可以使用此方法代替旧的 viewDidUnload。

        // The completion handler, if provided, will be invoked after the dismissed controller's viewDidDisappear: callback is invoked.
        - (void)dismissViewControllerAnimated: (BOOL)flag completion: (void (^)(void))completion NS_AVAILABLE_IOS(5_0);
        

        Swift 2017 语法:

        override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
            if (yourChildViewController  != nil) {
              print("good thing we did this!")
            }
            yourChildViewControllerProperty = nil
            super.dismiss(animated: flag, completion: completion)
        }
        

        【讨论】:

        • 一般是2017年最好的答案
        猜你喜欢
        • 2011-05-20
        • 2011-07-01
        • 2023-03-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-10
        • 2011-10-14
        • 1970-01-01
        相关资源
        最近更新 更多