【问题标题】:How can I find who is retaining an object?我怎样才能找到谁在保留一个对象?
【发布时间】:2014-12-04 16:13:56
【问题描述】:

UITableView 向解除分配的委托发送消息时遇到问题。 当调用拥有 tableView 的 UIViewController 中的 dealloc 时,tableView 仍然处于活动状态,并且 tableView 正在向其委托发送消息。当 tableView 的所有者在 dealloc 中释放 tableview 时,通过设置 delegate = nil 来解决此崩溃。如果内存管理正确,我相信这是没有必要的。

我想知道如何找出谁在保留 tableView。

有什么办法可以解决吗?

谢谢!

【问题讨论】:

    标签: ios xcode cocoa-touch instruments


    【解决方案1】:

    您的tableView 在其委托被清理后继续处理;请记住,委托被分配给weak 引用属性,因此UITableView 不会保留。如果您正在折叠ViewControllerUITableView 仍在加载元素,您将看到此崩溃。如果要释放的类是委托,最好在你的 dealloc 中分配 .delegate = nil

    【讨论】:

    • "记住委托被分配给弱引用属性" - UITableView 的委托设置为@property(nonatomic, assign) id 委托,这就是为什么tableView 仍然可以向对象发送消息已被释放。
    • 没错 - UITableView 是在 ARC 之前创建的,因此您可以考虑 assign == weakretain == strong。在您的UITableViewDelegate 被释放后,UITableView 不再能够向该对象发送消息,因为该对象不存在。但是,它可以尝试向您的UITableViewDelegate 先前占用的内存地址处的对象发送消息;这通常会导致 EXC_BAD_ACCESS。
    【解决方案2】:

    当 tableView 的所有者在 dealloc 中释放 tableview 时,通过设置 delegate = nil 来解决此崩溃。如果内存管理正确,我相信这是没有必要的。

    这在今天通常是正确的,因为委托通常被声明为weak,这意味着当底层对象被释放时它们会自动设置为nil。但是UITableView 比这更老。它来自 ARC 之前的日子,并声明了它的代表:

    @property(nonatomic, assign) id<UITableViewDelegate> delegate
    

    因此,如果委托被解除分配,UITableView 将指向未分配的内存。

    这种崩溃通常意味着您正在尝试更新不在屏幕上的 tableview。根据我的经验,最常见的原因是在不应该的时候观察通知。您要确保在viewWillAppear: 中观察到通知,并在viewDidDisappear: 期间删除所有观察结果。同样,当你离开屏幕时你不应该观察 KVO(但我更经常发现这种崩溃表示NSNotification)。

    您还应该确保委托以外的任何对象都不能直接访问 tableview。任何人都不应该从视图/委托关系之外调用reloadData 或类似的东西。任何人都不应访问委托的 IBOutlet 属性。这类事情会导致这类崩溃。委托之外的任何人都不应该有对表格视图的引用。

    当然,请确保您没有在后台线程上更新表格视图。这里可能不是这种情况。它往往会导致其他类型的崩溃。但这是另一种可能性。

    【讨论】:

      【解决方案3】:

      使用 Instruments 启动您的项目(Xcode 中的菜单 Product->Profile)并选择 Leaks。它将记录已创建、保留、释放、自动释放、释放的每个对象。您甚至可以在那里搜索内存地址。因此,您需要做的就是获取对象的内存地址,例如您可以将其打印到控制台。大多数人不知道,但您可以从仪器中查看控制台:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-02-24
        相关资源
        最近更新 更多