Вы не можете разыменовать ivars с ->
, если this
равно nil
. Таким образом, типичное решение - создать надежную ссылку, которую нельзя освободить во время выполнения закрытия, и return
, если nil
:
- (NSString * _Nullable)process {
typeof(self) __weak weakSelf = self;
[self asynchronousMethodWithCompletion:^{
typeof(self) strongSelf = weakSelf;
if (!strongSelf) { return; }
// can now safely use `strongSelf` here
});
...
}
Это «weakSelf
- strongSelf
танец». Вы используете его в ситуациях, когда вам нужно убедиться, что self
не nil
, когда вы его используете, например, разыменование иваров (strongSelf->ivar
).
Таким образом:
- (NSString * _Nullable)process {
typeof(self) __weak weakSelf = self;
NSString __block *ret = nil;
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
dispatch_async(_repQueue, ^{
typeof(self) strongSelf = weakSelf;
if (!strongSelf) { return; }
[strongSelf updateFromTable:[strongSelf->_env table] env:strongSelf->_env callback:^{
ret = [some op .. ];
dispatch_group_leave(group);
}];
});
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
info(@"%@", @"done");
return ret;
}
Несколько других наблюдений:
Группа отправки должна быть локальной переменной метода, а не ivar. В вашем коде больше ничего не нужно ссылаться на этот group
.
Убедитесь, что ваши dispatch_group_leave
вызовы не превышают количество dispatch_group_enter
вызовов (т. Е. Этот блок обработчика завершения не вызывается несколько раз).
Я бы предложил подождать DISPATCH_TIME_FOREVER
(при условии, что вы действительно хотите дождаться его завершения).
Кроме того, если это свойства (которые, как я предполагаю, основаны на подчеркивании), то использование self.env
вместо self->_env
безопаснее, поскольку не произойдет сбой, если self
is nil
, а скорее просто вернет nil
.
Я должен признаться, что это все еще не выглядит правильным (например, если updateFromTable
уже асинхронный, зачем беспокоиться об отправке этого асинхронно в _repQueue
; если это синхронно, то опять же, зачем отправлять это асинхронно только для ожидания Это). Но невозможно комментировать дальше, не увидев реализацию updateFromTable
.
Или, лучше, сделать метод асинхронным:
- (void)processWithCompletion:(void (^)(NSString *))callback {
typeof(self) __weak weakSelf = self;
dispatch_async(_repQueue, ^{
typeof(self) strongSelf = weakSelf;
if (!strongSelf) { return; }
[strongSelf updateFromTable:[strongSelf->_env table] env:strongSelf->_env callback:^{
NSString *ret = [some op .. ];
callback(ret);
}];
});
}