Второе исправление заключается в использовании __block
у установить указатель NSError изнутри блока в проекте, используя автоматический подсчет ссылок. Далее следует упрощенная версия моего кода:
- (BOOL)frobnicateReturningError:(NSError **)error
{
NSArray *items = [NSArray arrayWithObjects:@"One", @"Two", @"Three", nil];
__block Frobnicator *blockSelf = self;
[items enumerateObjectsUsingBlock:^(id item, NSUInteger idx, BOOL *stop) {
[blockSelf doSomethingWithItem:item error:error];
}];
}
Это компилируется но даетсяerror
может быть измененdoSomethingWithItem
Я попытался создать локальный NSError для блока, чтобы изменить, который затем будет использоваться для установки оригиналаerror
после перечисления (которое я не показал):
- (BOOL)frobnicateReturningError:(NSError **)error
{
NSArray *items = [NSArray arrayWithObjects:@"One", @"Two", @"Three", nil];
__block Frobnicator *blockSelf = self;
__block NSError *blockError = nil;
[items enumerateObjectsUsingBlock:^(id item, NSUInteger idx, BOOL *stop) {
[blockSelf doSomethingWithItem:item error:&blockError];
}];
}
Это не компилируется со следующей ошибкой:
передача адреса нелокального объекта в параметр __autoreleasing для обратной записи
Поиск этой ошибки в Google возвращает результаты только из исходного кода Clang.
Одно решение, которое кажется работающим, но немного уродливым, это иметь внутренний и внешний указатель ошибки:
- (BOOL)frobnicateReturningError:(NSError **)error
{
NSArray *items = [NSArray arrayWithObjects:@"One", @"Two", @"Three", nil];
__block Frobnicator *blockSelf = self;
__block NSError *outerError = nil;
[items enumerateObjectsUsingBlock:^(id item, NSUInteger idx, BOOL *stop) {
NSError *innerError = nil;
[blockSelf doSomethingWithItem:item error:&innerError];
outerError = innerError;
}];
}
Как правильно установить NSError из блока?