ema*_*cos 2 pointers function objective-c ios swift
我正在学习本教程,特别是在使用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;
}
Run Code Online (Sandbox Code Playgroud)
对此,在init函数中是context变量给我带来的问题.
在上面的代码中,context是一个类型的变量:CFRunLoopSourceContext在apple文档中初始化这个对象是这样的
所以,我在初始化时,使用了以下代码,专注于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)
Run Code Online (Sandbox Code Playgroud)
功能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)
}
Run Code Online (Sandbox Code Playgroud)
但编译器给我以下错误信息: 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)
}
Run Code Online (Sandbox Code Playgroud)
我这样说:
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)
Run Code Online (Sandbox Code Playgroud)
给了我同样的错误.问题是什么 ?有小费吗
如果您func RunLoopSourceScheduleRoutine()用作回调,则它需要是全局函数,而不是实例方法.
如果将回调定义为闭包,则需要将其标记为纯C回调:
let runLoopSourceScheduleRoutine: @convention(c) (UnsafeMutableRawPointer?, CFRunLoop?, CFRunLoopMode?) -> Void =
{ (info, rl, mode) in
let obj = Unmanaged<RunLoopSource>.fromOpaque(info!).takeUnretainedValue()
// ...
}
Run Code Online (Sandbox Code Playgroud)
或者,将闭包表达式传递给编译器将类型推断为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)
Run Code Online (Sandbox Code Playgroud)
另请注意,您必须打开方法obj,而不是打开方法self.我建议使用GCD而不是performSelector(),这允许编译器检查是否使用正确的参数调用该方法:
let obj = Unmanaged<RunLoopSource>.fromOpaque(info!).takeUnretainedValue()
let theContext = RunLoopContext(withSource: obj, andLoop: rl!)
DispatchQueue.main.async {
obj.myMethod(theContext)
}
Run Code Online (Sandbox Code Playgroud)