Как лить блоки в и из void *
Итак, я пытаюсь передать блок как параметр NSAlert
contextInfo
.
[myAlert beginSheetModalForWindow: theWindow
modalDelegate: myAlert
didEndSelector: @selector(alertDidEnd:returnCode:contextInfo:)
contextInfo: (void *) aBlock];
и верните его на другой конец:
void (^responseBlock)() = (__bridge_transfer void (^)()) contextInfo;
Что работает, в какой-то степени. До моего вызова beginSheetModalForWindow:...
aBlock находится в 0x00007fff610e1ec0
, а в ответе (alertDidEnd:...
) contextInfo находится в 0x00007fff610e1ec0
.
Однако, когда я пытаюсь вызвать блок:
responseBlock();
Я получаю следующую ошибку
error: называемый тип объекта '__block_literal_generic *' не является указателем функции или функции
Ошибка: 1 ошибка разбора выражения
Как правильно отбрасывать блоки с void *
для простого переноса?
Edit:
Полностью выполненный код, используя методы литья, предложенные в ответах. Теперь я получаю ошибку EXC_BAD_ACCESS при вызове responseBlock();
.
- (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo
{
void (^responseBlock)() = (__bridge typeof(responseBlock)) contextInfo;
switch (returnCode)
{
case NSCancelButton:
{
break;
}
case NSOKButton:
{
responseBlock();
break;
}
}
}
Другие примечания:
При использовании __bridge
адрес памяти responseBlock
и contextInfo
различен, тогда как при __bridge_transfer
они совпадают. Не уменьшает проблему с EXC_BAD_ACCESS.
РАБОЧИЕ:
[myAlert beginSheetModalForWindow: theWindow
modalDelegate: myAlert
didEndSelector: @selector(alertDidEnd:returnCode:contextInfo:)
contextInfo: (__bridge_retained void *) [aBlock copy]];
и позже...
void (^responseBlock)() = (__bridge_transfer typeof(responseBlock)) contextInfo;
Ответы
Ответ 1
Вот небольшой пример. Я думаю, что проблема с вашим кодом заключается в том, что вы пытаетесь использовать __bridge_transfer
с void *
, который не управляется памятью с помощью ARC:
void takesBlock(void *asPointer)
{
void (^asBlock)() = (__bridge typeof asBlock) asPointer;
asBlock();
}
int main()
{
@autoreleasepool {
takesBlock((__bridge void *)[^{
NSLog(@"Hello World!");
} copy]);
}
}