我使用NSProgress通知复杂任务的进度(该任务由多个子任务组成,可以由其他子任务组成)。
我创建了startTask方法的主要进展:
- (void)_startTask
{
_progress = [NSProgress progressWithTotalUnitCount:100]; //sometimes crash is here
<...>
}没有currentProgress:
(lldb) po NSProgress currentProgress 零
有时,我会与奇怪的stackTrace发生碰撞:
object_isClass ()中的0: 0x000000018539a7e8 KVO_IS_RETAINING_ALL_OBSERVERS_OF_THIS_OBJECT_IF_IT_CRASHES_AN_OBSERVER_WAS_OVERRELEASED_OR_SMASHED ()中的1: 0x0000000186b39fe0 2: 0x0000000186b384bc () 3: 0x0000000186仙人掌9c0 in -setValueForKeys:settingBlock: 4: 0x0000000186cacc7c in -NSProgress setTotalUnitCount: +NSProgress progressWithTotalUnitCount:中的5: 0x0000000186CA718
此代码在mainThread中执行。
为什么会发生这种情况,我能做些什么来避免这种情况呢?
发布于 2018-03-13 08:11:56
似乎您已经释放了一个或多个NSProgress对象,而没有移除它们的键值观察者。
您可以看看这个:https://github.com/AFNetworking/AFNetworking/issues/3710
“0xsted”的评论清楚地指出了这种情况发生的原因:
这是一些有趣的数据。 NSProgress实例有时会重新分配一个以前由另一个NSProgress实例使用的地址:例如,0x7ffa6a119730分配给一个下载进度,然后分配一个上传进度,然后分配另一个下载进度(崩溃发生的地方)。这就解释了为什么启用僵尸的运行会使崩溃消失:地址永远不会被重用,因为已分配的objet会变成僵尸,并且永远保留原来的地址。 当重用相同的地址(0x7ffa6a119730)时,NSProgress实例在其创建后立即有一个观察者。这个观察者是0x7ffa68c0bab0,一个旧的AFURLSessionManagerTaskDelegate实例。
发布于 2019-01-03 09:33:21
这种崩溃发生在我的应用程序的所有版本的iOS,因为它是建立(自从iOS 10)。
我的进度报告实现类似于苹果的WWDC 2015 talk - 进度报告最佳做法,其中进度对象被嵌套,调用parentProgress.addChild(childProgress, withPendingUnitCount: value)作为父任务,创建新的子任务并添加到调度队列中。
我假设,当父进度对象被解除分配时,它将停止观察子进度更改(没有公共remove child方法)。这应该是真的,但我怀疑实现并不是线程安全的。
总之,我修改了我的实现以使用一个单个进度对象来避免多个进度对象的问题。
https://stackoverflow.com/questions/47549148
复制相似问题