Этот вопрос похож на этот вопрос с добавлением автоматического подсчета ссылок.
У меня есть подкласс NSOperation
, который принимает аргумент блока, который предназначен в качестве обратного вызова для основного(UI) поток.Мое первоначальное намерение состояло в том, чтобы выполнить некоторую операцию в фоновом режиме, а затем использовать dispatch_async
и основную очередь для выполнения обратного вызова.
Исходное условие:
@interface MySubclass : NSOperation {
@protected
dispatch_block_t _callback;
}
- (id)initWithCallback:(dispatch_block_t)callback;
@end
@implementation MySubclass
- (void)main
{
// Do stuff
if (![self isCancelled]) {
dispatch_async(dispatch_get_main_queue(), _callback);
}
}
@end
Проблемы возникают, когда все ссылкик объекту UIKit вне области блока удаляются.(Например, UIViewController
выталкивается из стека навигации.) Это оставляет единственную ссылку на объект внутри блока, поэтому объект освобождается, когда блок находится, в потоке, где блок освобожден ,Отмена выделения объекта UIKit из основного потока приводит к сбою приложения с сообщением об ошибке Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now...
В качестве обходного пути я добавил модификатор __block
в callar ivar и использую dispatch_sync
, чтобы убедиться, что всеРелиз находится в главном потоке.
@interface MySubclass : NSOperation {
@protected
__block dispatch_block_t _callback;
}
- (id)initWithCallback:(dispatch_block_t)callback;
@end
@implementation MySubclass
- (void)main
{
// Do Stuff
if (![self isCancelled]) {
dispatch_block_t block = ^{
_callback();
_callback = nil;
};
// Cover all our bases to prevent deadlock
if ([NSThread isMainThread]) block();
else dispatch_sync(dispatch_get_main_queue(), block);
}
}
@end
Мне интересно, есть ли лучший способ добиться чего-либо с этой предпосылкой.Мой обходной путь кажется хакерским, и мне не нравится, что я мог бы закончить несколькими операциями в моей очереди, все из которых ожидают поворота основного потока, прежде чем они могут завершиться.