У меня есть ErrorBlock (errorBlock), определенный в моем коде, который можно вызывать несколько раз. Хотя я хочу, чтобы меня проинформировали только один раз, поэтому моя идея заключалась в том, чтобы обернуть мой ErrorBlock (errorBlock) внутри другого (pErrorBlock) и установить для него значение nil.
Теперь я хотел иметь метод очистки, который устанавливает ссылки на innerBlock равными нулю. Но когда я передаю внутренний блок методу очистки (тест 1), я получаю другой результат, чем когда я устанавливаю внутренний блок ErrorBlock nil self (тест 2).
Как я могу получить результат теста 2 с (немного измененным) кодом теста 1?
Мой первый тест, обувь результат, который я не понимаю:
-(void)testBlocks{
__block ErrorBlock pErrorBlock= ^(void){
NSLog(@"Foo");
};
NSLog(@"test: %p",pErrorBlock);
ErrorBlock errorBlock = ^(void){
dispatch_async(dispatch_get_main_queue(), ^{
if(pErrorBlock){
NSLog(@"call: %p",pErrorBlock);
pErrorBlock();
}
[self cleanupErrorBlockWith:pErrorBlock];
});
};
errorBlock();
errorBlock();
}
- (void) cleanupErrorBlockWith:(ErrorBlock)errorBlock{
NSLog(@"cleanup: %p",errorBlock);
errorBlock = nil;
NSLog(@"after cleanup: %p",errorBlock);
}
Результат:
2013-02-08 16:39:04.484 Tests[9501:907] test: 0x3a6ba8
2013-02-08 16:39:04.496 Tests[9501:907] call: 0x3a6ba8
2013-02-08 16:39:04.497 Tests[9501:907] Foo
2013-02-08 16:39:04.498 Tests[9501:907] cleanup: 0x3a6ba8
2013-02-08 16:39:04.499 Tests[9501:907] after cleanup: 0x0
2013-02-08 16:39:04.500 Tests[9501:907] call: 0x3a6ba8
2013-02-08 16:39:04.501 Tests[9501:907] Foo
2013-02-08 16:39:04.502 Tests[9501:907] cleanup: 0x3a6ba8
2013-02-08 16:39:04.503 Tests[9501:907] after cleanup: 0x0
Мой второй тест с желаемым результатом:
-(void)testBlocks{
__block ErrorBlock pErrorBlock= ^(void){
NSLog(@"Foo");
};
NSLog(@"test: %p",pErrorBlock);
ErrorBlock errorBlock = ^(void){
dispatch_async(dispatch_get_main_queue(), ^{
if(pErrorBlock){
NSLog(@"call: %p",pErrorBlock);
pErrorBlock();
NSLog(@"cleanup: %p",pErrorBlock);
pErrorBlock = nil;
NSLog(@"after cleanup: %p",pErrorBlock);
}
});
};
errorBlock();
errorBlock();
}
Результат:
2013-02-08 16:42:18.485 Tests[9540:907] test: 0x3a6ba8
2013-02-08 16:42:18.496 Tests[9540:907] call: 0x3a6ba8
2013-02-08 16:42:18.498 Tests[9540:907] Foo
2013-02-08 16:42:18.499 Tests[9540:907] cleanup: 0x3a6ba8
2013-02-08 16:42:18.500 Tests[9540:907] after cleanup: 0x0
1 ответ
Вы передаете блок по значению, передайте его по ссылке следующим образом. Также перемещаем ваш вызов cleanupErrorBlockWith:
внутри оператора if
.
-(void)testBlocks{
__block ErrorBlock pErrorBlock= ^(void){
NSLog(@"Foo");
};
NSLog(@"test: %p",pErrorBlock);
ErrorBlock errorBlock = ^(void){
dispatch_async(dispatch_get_main_queue(), ^{
if(pErrorBlock){
NSLog(@"call: %p",pErrorBlock);
pErrorBlock();
[self cleanupErrorBlockWith:&pErrorBlock];
}
});
};
errorBlock();
errorBlock();
}
- (void) cleanupErrorBlockWith:(ErrorBlock*)errorBlock{
NSLog(@"cleanup: %p",*errorBlock);
*errorBlock = nil;
NSLog(@"after cleanup: %p",*errorBlock);
}
ErrorBlock
, я бы ответил на ваш вопрос на 5 минут раньше. : D В любом случае +1 за ваш вопрос, так как он проясняет мою концепцию создания блочных переменных :)
Похожие вопросы
Новые вопросы
ios
iOS - мобильная операционная система, работающая на Apple iPhone, iPod touch и iPad. Используйте этот тег [ios] для вопросов, связанных с программированием на платформе iOS. Используйте связанные теги [target-c] и [swift] для проблем, характерных для этих языков программирования.
errorBlock = nil;
не имеет никакого эффекта, учитывая, что он передан как параметр ...