为什么使用 ARC + NSZombieEnabled 时对象未释放

2024-02-22

我将我的应用程序转换为 ARC,并注意到当视图控制器被释放时,在我的视图控制器之一中分配的对象没有被释放。我花了一段时间才弄清楚原因。我在调试时为我的项目启用了“启用僵尸对象”,结果证明这就是原因。考虑以下应用程序逻辑:

1)用户调用actionRootViewController这会导致SecondaryViewController通过创建和呈现presentModalViewController:animated.

2) SecondaryViewController包含一个ActionsController那是一个NSObject子类。

3) ActionsController通过观察通知NSNotificationCenter当它被初始化并在它被释放时停止观察。

4)用户拒绝SecondaryViewController返回到RootViewController.

关闭启用僵尸对象后,上述工作正常,所有对象都被释放。启用“启用僵尸对象”ActionsController即使没有被释放SecondaryViewController被解除分配。

这导致我的应用程序 b/c 出现问题NSNotificationCenter继续发送通知至ActionsController生成的处理程序会导致应用程序崩溃。

我创建了一个简单的应用程序来说明这一点https://github.com/xjones/XJARCTestApp https://github.com/xjones/XJARCTestApp。查看控制台日志并打开/关闭“启用僵尸对象”以验证这一点。

问题)

  1. 这是启用僵尸对象的正确行为吗?
  2. 我应该如何实现这种逻辑来消除这个问题。我想继续使用启用僵尸对象。

编辑 #1:根据 Kevin 的建议,我已将其提交给 Apple 和 openradarhttp://openradar.appspot.com/10537635 http://openradar.appspot.com/10537635.

编辑#2:澄清一个好的答案

首先,我是一名经验丰富的 iOS 开发人员,我完全了解 ARC、僵尸对象等。如果我遗漏了什么,当然,我很感激任何启发。

其次,确实,此特定崩溃的解决方法是删除actionsController作为观察者,当secondaryViewController被解除分配。我还发现,如果我明确设置actionsController = nil when secondaryViewControlleris dealloc'ed 它将被dealloc'ed。这两种方法都不是很好的解决方法,因为它们实际上要求您使用 ARC,但编码就好像您没有使用 ARC(例如,在 dealloc 中显式设置 nil iVars)。特定的解决方案也无助于确定其他控制器中何时会出现此问题,因此开发人员可以确定地知道何时/如何解决此问题。

一个好的答案将解释如何确定性地知道在使用 ARC + NSZombieEnabled 时需要对对象做一些特殊的事情,这样它就可以解决这个特定的示例,并且通常也适用于整个项目,而不会留下其他类似的可能性问题。

完全有可能不存在一个好的答案,因为这可能是 XCode 中的一个错误。

谢谢大家!


原来我写了一些严重的废话

如果僵尸像我原来写的那样工作的话,打开僵尸会直接导致无数误报……

有一些 isa-swizzling 正在进行,可能在_objc_rootRelease,所以任何重写dealloc仍应在启用僵尸的情况下调用。僵尸唯一不会发生的事情是实际调用object_dispose——至少默认情况下不是。

有趣的是,如果您进行一些日志记录,您实际上会发现即使启用了 ARC,您的实现dealloc将调用它的超类的实现。

我实际上假设根本看不到这一点:因为 ARC 生成了这些时髦的.cxx_destruct方法来处置任何__strong一个班级的伊瓦尔,我期待看到this方法调用dealloc——如果实施的话。

显然,设置NSZombieEnabled to YES causes .cxx_destruct根本不被调用——至少当我编辑你的示例项目时发生了这样的情况:
僵尸关闭导致回溯和两次释放,而僵尸打开则不产生回溯并且仅产生一次释放。

如果您有兴趣,附加日志记录包含在示例项目的一个分支 https://github.com/danyowdee/XJARCTestApp- 只需运行即可工作:有两种用于僵尸开/关的共享方案。


原始(无意义)答案:

这不是一个错误,而是一个功能。

而且和ARC没有任何关系。

NSZombieEnabled基本上是混合的dealloc对于一个实现,反过来,isa-swizzles 该对象的类型_NSZombie——只要你向它发送任何消息,一个虚拟类就会爆炸。这是预期的行为,并且(如果我没有完全弄错的话)已记录在案。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么使用 ARC + NSZombieEnabled 时对象未释放 的相关文章

  • 具有多种自定义单元格类型的 RxSwift 表视图

    我想知道是否有任何代码示例RxSwift当我可以在一个表视图中使用多个自定义单元格时 例如 我有两个部分 第一部分有 10 个单元格 类型为CellWithImage标识符和第二部分有 10 个带有类型的单元格CellWithVideo标识
  • 增加 NSData 的长度

    基本上 我有一个 46 个字符的 NSString 我将其转换为 NSData 我需要将字符串填充到 48 个字符 仅在 NSString 末尾添加 是行不通的 所以 我只是使用以下方法增加了 NSData 的长度 NSString str
  • 为什么 GDB 调试器不断冻结 Xcode 4?

    这真是一个奇怪的错误 我正在开发一个使用相机源的 iPhone 项目 并通过 OpenGL 着色器运行它以对其应用效果 然而 每次我在代码中简单地创建一个新的 GLfloat 时 调试器都会在启动时冻结 我无法复制和粘贴文本 因为整个 XC
  • 当设置 setVisibleXRangeMaximum 时,iOS-Charts X 轴值无限重复

    我正在尝试绘制一个图表 其中 x 轴是TimeIntervalY 轴是power consumption 由于每天都会有数据 因此将有太多数据无法显示 因此 我想一次显示 5 个值 我通过设置实现了这一点self chart setVisi
  • 蓝牙 4.0 与较旧的蓝牙

    我正在尝试使用蓝牙 4 0 模块实现一个应用程序 我想知道将此应用程序与包含简单蓝牙 2 1 EDR 模块的 Iphone 3GS 一起使用是否能让我利用 4 0 模块中的低功耗 谢谢您的回答 蓝牙 4 0 是标准 其中包括经典蓝牙基本速率
  • UICollectionView 列的垂直偏移

    右图是我试图实现的目标 Does anyone know how I could achieve this on a two column UICollectionView I m able to discern my columns by
  • Xcode 9.0.1 应用程序分发程序已更改

    最近我将 Xcode 升级到了 Xcode 9 1 之后 当我尝试发布我的应用程序时 Xcode 不允许选择我为临时创建的分发配置文件 这么说 配置文件不是 IOS 应用商店配置文件 如果 Xcode 9 1 的应用程序分发过程有变化 请告
  • ObjC <-> Swift 桥接和工厂方法

    我想从 Swift 使用一些 Objective C 类 由于超出了这个问题范围的原因 我的班级init方法被标记为不可用 相反 有一个工厂方法 这是我的班级的简化形式 interface MyClass NSObject instance
  • 使用原始类型+大小写参数的 Swift Enum 的解决方法?

    我想创建 SKSpriteNodesWallType 请参阅下面的代码 并且仅当WallType is Corner通过它Side其方向的价值 枚举具有原始值 因为我需要将它们作为数字从 plist 加载 并能够随机创建它们 enum Si
  • 如何在 SwiftUI 中呈现视图而不将其嵌入到当前导航流中?

    我已经完成了日志记录入门 并且需要呈现一个 HomeView 它对之前的导航流程一无所知 var body some View if viewModel isValidated destination else LoadingView 通过
  • 防止 UITableView 滚动到某个点以下

    如何让 UITableView 允许在某个索引行上方滚动 但在低于某个点时阻止滚动 例如 如果我有第 1 行到第 100 行 其中在给定时间视图中仅出现 5 行 我希望允许用户在第 1 50 行之间滚动 但在第 50 行可见时阻止进一步向下
  • 以编程方式添加带有自动布局的 UISLider

    我正在尝试以编程方式将 UISlider 添加到我的视图中 包括约束 以便其宽度适应整个屏幕宽度 这是我到目前为止得到的 2 Add UISlider self slider UISlider alloc init self view ad
  • 当 Firebase 函数以 Swift 结束时

    我在我的应用程序中使用 Firebase 它查询大量用户并获取所需的特定数据 但是当它开始查询时 其余功能也继续运行 而不仅仅是查询 所以我无法理解当它结束时 例如在这段代码中 ref observeEventType ChildAdded
  • ios - 使用 SIGPIPE 和 SIG_IGN 的信号函数

    我加入了一个旧项目 我发现了这条线 BOOL application UIApplication application didFinishLaunchingWithOptions NSDictionary launchOptions si
  • 如何检测iPhone是否有视网膜显示屏?

    如何检测 iPhone 是否配备视网膜显示屏 有靠谱的办法吗 要么是纯 PHP 要么最好是 Zend Framework 方式来执行此操作 我通过这个弄清楚了 var retina window devicePixelRatio gt 1
  • iOS 4.0 中的应用程序将终止

    iOS 4 0 中未调用 applicationWillTerminate 委托方法 当我点击 主页 按钮时 我看到 applicationWillResignActive 和 applicationDidEnterBackground 委
  • iOS SDK:MapKit MKPolyLine 未显示

    我试图在地图上显示多段线 但该线没有显示 我尝试了很多事情 但注意到似乎有用 我检查了核心数据函数 它正在返回数据 所以这不是问题 它必须是我在地图点创建或地图上绘制的某个地方 我猜 我确信一定是某个地方出了点小错误 但我找不到它 My c
  • UIWebView 内的滑动手势识别

    我已经阅读了很多关于此的问题 但似乎没有一个能够实现我想要的 所以可以说我有一个任意的UIWebView里面的一个UIViewController The UIViewController has a SwipeGestureRecogni
  • UITableViewController 无法识别的选择器发送到实例

    当我传递一个整数时 我有一个 tableviewcontroller 和一个detailtableviewcontroller UITableViewController setSurveyNumber 无法识别的选择器发送到实例 Biza
  • 将我的免费应用程序从 Universal 升级到仅限 iPhone

    我释放我的free app到 appStore 它的版本是 1 0 它是一个Universal app 现在我想发布 1 1 版本到 appStore 我将其升级到iPhone only appStore会拒绝我吗 我已阅读类似的问题 ht

随机推荐