我在我的应用程序内部遇到EXC_BAD_ACCESS
错误,根据我的理解,该实际上应该捕获涉及此内容的所有内容,因此无法在块中释放它。 (ARC已启用)
这是我的代码:
- (void)_perform_async_onqueue:(void (^)(void))task {
dispatch_async(self.workerQueue, task);
}
- (void)cancel {
[self _perform_async_onqueue:^{
// operation is strongly retained by self.
// operation is also retained by an operation queue.
// within `cancel` the operation is released from the operation queue
[self.operation cancel];
}
}];
这在[self.operation cancel]
内崩溃。 self.operation
是NSOperation
的子类。操作的cancel
方法详细说明:
- (void)cancel {
[self willChangeValueForKey:@"isCancelled"];
_cancelled = YES;
[self didChangeValueForKey:@"isCancelled"];
[self willChangeValueForKey:@"isFinished"];
[self willChangeValueForKey:@"isExecuting"];
_finished = YES;
_executing = NO;
[self didChangeValueForKey:@"isExecuting"];
[self didChangeValueForKey:@"isFinished"]; // CRASH (debugger lists `self` [= the operation] as `nil` in this line
}
据我所知,第一个self
应该保留在调度块中。由于self
对strong
有一个operation
引用,所以这也应该在内存中,直到块执行结束。这怎么会导致EXC_BAD_ACCESS
崩溃?
答案 0 :(得分:1)
答案 1 :(得分:0)
方法没有对自我的强烈引用。如果在调用方法时取消分配self,则由您自己完成。 (这就是为什么你在弱对象上调用方法时会收到警告的原因,因为在方法运行时对象可能会消失)。
你可以指定SomeClass *我自己= self;这将使自己保持活力直到方法结束。
你也可以实现你自己的dealloc(它只是自动调用[super dealloc])并设置一个断点来找出当 self被解除分配时,更好地理解事物。
答案 2 :(得分:0)
我发现了这个问题:
事实证明,所述行为完全正常。问题是这里使用的NSOperation
是一个自定义的异步操作,它以错误的方式实现了取消:如果取消之前的操作它已由{{ 1}}操作队列然后过度释放操作。这就是操作被解除分配的原因,即使仍有强大的引用应该保留它。
我会为此提交文件。