如何铸造块和从void * [英] How to cast blocks to and from void *

查看:194
本文介绍了如何铸造块和从void *的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,我试图传递一个块作为 NSAlert contextInfo 参数。

So, I'm trying to pass a block as an NSAlert contextInfo parameter.

[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

Which works, to an extent. Before my call to beginSheetModalForWindow:... aBlock is at 0x00007fff610e1ec0, and in the response (alertDidEnd:...), contextInfo is at 0x00007fff610e1ec0.

当我尝试调用块:

responseBlock();

我收到以下错误


错误:调用的对象类型__block_literal_generic *不是函数或函数指针

错误:解析表达式时出现错误

error: called object type '__block_literal_generic *' is not a function or function pointer
error: 1 errors parsing expression

为了简单的转移,如何正确地从 void * 转换块?

How does one properly cast blocks to an from void *s for the sake of simple transference?

修改:
完整尝试的代码,使用答案中建议的投放方法。我现在在 responseBlock(); 调用上收到一个EXC_BAD_ACCESS错误。

Full attempted code, using the cast methods suggested in the answers. I now receive an EXC_BAD_ACCESS error on the responseBlock(); call.

- (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问题。

Other Notes: When using __bridge, the memory address of responseBlock and contextInfo are different, whereas with __bridge_transfer, they are the same. Neither alleviates the EXC_BAD_ACCESS issue.

[myAlert beginSheetModalForWindow: theWindow
                    modalDelegate: myAlert
                   didEndSelector: @selector(alertDidEnd:returnCode:contextInfo:)
                      contextInfo: (__bridge_retained void *) [aBlock copy]];

及更高版本...

void (^responseBlock)() = (__bridge_transfer typeof(responseBlock)) contextInfo;


推荐答案

我认为你的代码的问题是你试图使用 __ bridge_transfer void * 这不是用ARC管理的内存:

Here's a small example. I think that the problem with your code is that you are trying to use __bridge_transfer with a void * which isn't memory managed with ARC:

void takesBlock(void *asPointer)
{
    void (^asBlock)() = (__bridge typeof asBlock) asPointer;

    asBlock();
}

int main()
{
    @autoreleasepool {
        takesBlock((__bridge void *)[^{
            NSLog(@"Hello World!");
        } copy]);
    }
}

这篇关于如何铸造块和从void *的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆