33

因此,viewDidUnload从 iOS 6 开始已弃用,我现在需要做什么?

删除它,将它的所有内容迁移到 中didReceiveMemoryWarning,或者留下它,不做任何事情didReceiveMemoryWarning

4

5 回答 5

68

简短的回答是,在许多情况下,您不需要更改任何内容。而且,您当然不想简单地将所有内容迁移viewDidUnloaddidReceiveMemoryWarning.

通常,我们大多数人都会设置对in的IBOutlet引用(主要是因为 Interface Builder 会为我们放置它)并在. 如果您就是这样做的,那么您可能不需要任何代码更改。nilviewDidUnloaddidReceiveMemoryWarning

根据 iOS 6viewDidUnload文档:

在低内存条件下不再清除视图,因此永远不会调用此方法。

因此,您希望将IBOutlet引用设置移动到nil任何地方,因为不再清除视图。将它们设置为nilindidReceiveMemoryWarning或类似的东西是没有意义的。

但是,如果您通过viewDidUnloaddidReceiveMemoryWarning. 但话又说回来,我们大多数人已经在那里有了它。

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

正如 applefreak 所说,这取决于你在viewDidUnload. 如果您用您的viewDidUnload.

于 2012-10-01T15:54:20.567 回答
61

简短的回答:

切勿使用 -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. 还有viewWillAppearand viewDidDisappear,但这些与视图/控制器的生命周期无关,而是与显示周期相关(另一方面, -...appear 方法非常适合取消/注册通知侦听器!)。因此,在每次显示之前和之后创建和销毁视图可能并不合适。dealloc是我们唯一可以确定在控制器生命周期结束时调用的方法。[super dealloc]请注意,如果您使用 ARC ,则不得调用:

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

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

ViewController 的生命周期

也许查看 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(可能会或可能不会被调用)
于 2013-03-01T10:46:51.530 回答
7

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

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];

    if ([self isBeingDismissed] || [self isMovingFromParentViewController])
    {
        // Do your viewDidUnload stuff
    }
}

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

于 2015-04-01T09:57:58.780 回答
1

取决于您在做什么,viewDidUnload但您可以使用didReceiveMemoryWarningdealloc发布数据。看到这个

于 2012-10-01T14:55:18.470 回答
1

在大多数典型情况下,可以使用此方法代替旧的 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)
}
于 2014-02-05T23:40:54.700 回答