【问题标题】:Function pointer in swiftswift中的函数指针
【发布时间】:2016-12-23 14:04:07
【问题描述】:

我正在关注这个tutorial,尤其是我在用 Swift 语言转换这个函数时遇到了问题:

- (id)init
{
    CFRunLoopSourceContext    context = {0, self, NULL, NULL, NULL, NULL, NULL,
                                    &RunLoopSourceScheduleRoutine,
                                    RunLoopSourceCancelRoutine,
                                    RunLoopSourcePerformRoutine};

    runLoopSource = CFRunLoopSourceCreate(NULL, 0, &context);
    commands = [[NSMutableArray alloc] init];

    return self;
}

其中,在init函数中是context变量给我出问题。

在上面的代码中,context是一个类型为CFRunLoopSourceContext的变量,而苹果文档中这个对象的初始化是like this

所以,我在初始化时使用了以下代码,专注于schedule 参数:

var context = CFRunLoopSourceContext(version: 0, info: bridge(obj: self) ,
                                         retain: nil,
                                         release: nil,
                                         copyDescription: nil,
                                         equal: nil,
                                         hash: nil,
                                         schedule: RunLoopSourceScheduleRoutine,
                                         cancel: nil,
                                         perform: nil)

函数RunLoopSourceScheduleRoutine是这样的:

    func RunLoopSourceScheduleRoutine(info:UnsafeMutableRawPointer? ,rl:CFRunLoop? , mode:CFRunLoopMode?)  {
    
    let obj :  RunLoopSource = Unmanaged<RunLoopSource>.fromOpaque(info!).takeUnretainedValue()
    let theContext = RunLoopContext(withSource: obj, andLoop: rl!)
    performSelector(onMainThread: #selector(myMethod), with: theContext, waitUntilDone: false)
    
}

但是编译器给了我以下错误信息:a c function pointer can only be formed from a reference to a 'func' or a literal closure

即使我做了以下关闭:

let runLoopSourceScheduleRoutine = { (info:UnsafeMutableRawPointer? ,rl:CFRunLoop? , mode:CFRunLoopMode?)-> Void in return
        
        let obj :  RunLoopSource = Unmanaged<RunLoopSource>.fromOpaque(info!).takeUnretainedValue()
        let theContext = RunLoopContext(withSource: obj, andLoop: rl!)
        performSelector(onMainThread: #selector(myMethod), with: theContext, waitUntilDone: false)
        
    }

我是这样说的:

var context = CFRunLoopSourceContext(version: 0, info: bridge(obj: self) ,
                                         retain: nil,
                                         release: nil,
                                         copyDescription: nil,
                                         equal: nil,
                                         hash: nil,
                                         schedule: runLoopSourceScheduleRoutine,
                                         cancel: nil,
                                         perform: nil)

给了我同样的错误。 问题是什么 ? 任何提示

【问题讨论】:

    标签: ios objective-c swift function pointers


    【解决方案1】:

    如果你使用func RunLoopSourceScheduleRoutine() 作为回调 那么它需要是一个全局函数,而不是实例方法。

    如果将回调定义为闭包,则需要对其进行标记 作为纯 C 回调:

    let runLoopSourceScheduleRoutine: @convention(c) (UnsafeMutableRawPointer?, CFRunLoop?, CFRunLoopMode?) -> Void =
        { (info, rl, mode) in
    
            let obj = Unmanaged<RunLoopSource>.fromOpaque(info!).takeUnretainedValue()
            // ...
    }
    

    或者,将闭包表达式传递给编译器 将类型推断为 C 回调:

    var context = CFRunLoopSourceContext(version: 0, info: UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque()) ,
                     retain: nil,
                     release: nil,
                     copyDescription: nil,
                     equal: nil,
                     hash: nil,
                     schedule: { (info, rl , mode) in
    
                        let obj = Unmanaged<RunLoopSource>.fromOpaque(info!).takeUnretainedValue()
                        // ...
                     }, cancel: nil,
                     perform: nil)
    

    还请注意,您必须在 obj 上调用该方法,而不是在 self 上。 我会推荐 GCD 而不是 performSelector(),这允许 编译器检查方法是否被正确调用 论据:

    let obj = Unmanaged<RunLoopSource>.fromOpaque(info!).takeUnretainedValue()
    let theContext = RunLoopContext(withSource: obj, andLoop: rl!)
    DispatchQueue.main.async {
        obj.myMethod(theContext)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多