Подтвердить что ты не робот

Как лить блоки в и из 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;
4b9b3361

Ответ 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]);
    }
}