使用 KVO_IS_RETAINING_ALL_OBSERVERS_OF_THIS_OBJECTS_IF_IT_CRASHES_AN_OBSERVER_WAS_OVERRELEASED_OR_SMASHED 创建时 NSProgress 崩溃

And*_*nov 4 ios nsprogress

我使用 NSProgress 来通知复杂任务的进度(该任务由许多子任务组成,可以由其他子任务组成)。
我在 startTask 方法中创建主要进度:

- (void)_startTask
{
    _progress = [NSProgress progressWithTotalUnitCount:100]; //sometimes crash is here
    <...>
}
Run Code Online (Sandbox Code Playgroud)

没有当前进度:

(lldb) po [NSProgress currentProgress]
nil

有时我会因为奇怪的 stackTrace 崩溃:

0:0x000000018539a7e8在object_isClass()
1:0x0000000186b39fe0在KVO_IS_RETAINING_ALL_OBSERVERS_OF_THIS_OBJECT_IF_IT_CRASHES_AN_OBSERVER_WAS_OVERRELEASED_OR_SMASHED()
2:0x0000000186b384bc在
NSKeyValueWillChangeWithPerThreadPendingNotifications()
3:0x0000000186cac9c0在- [NSProgress _setValueForKeys:settingBlock:]()
4:0x0000000186cacc7c在- [NSProgress setTotalUnitCount:]()
5:0x0000000186cab718在 +[NSProgress progressWithTotalUnitCount:] ()

此代码在 mainThread 中执行。
为什么会发生这种情况,我可以做些什么来避免这种情况?

小智 5

似乎您释放了一个或多个 NSProgress 对象而没有删除它们的键值观察者。

你可以看看这个:https : //github.com/AFNetworking/AFNetworking/issues/3710

来自“0xced”的评论清楚地说明了为什么会发生这种情况:

这是一些有趣的数据。

NSProgress 实例有时会被重新分配一个先前由另一个 NSProgress 实例使用的地址:例如,0x7ffa6a119730 被分配给一个下载进度,然后是一个上传进度,然后是另一个下载进度(发生崩溃的地方)。这解释了为什么在启用僵尸的情况下运行会使崩溃消失:地址永远不会被重用,因为释放的对象会变成僵尸并永远保留其原始地址。

当相同的地址 (0x7ffa6a119730) 被重用时,NSProgress 实例在创建后立即有一个观察者。该观察者是 0x7ffa68c0bab0,一个旧的 AFURLSessionManagerTaskDelegate 实例。