今天我们来介绍一下 @convention
特性关键字。
@convention
解释 @convention
特性是在 Swift 2.0 中引入的,用于修饰函数类型,它指出了函数调用的约定。用在以下几个地方:
@convention(c)
的函数类型,匹配 C 函数参数中的函数指针。 @convention(block)
的函数类型,匹配 Objective-C 方法参数中的 block 参数。 @convention
使用举例 我们定义了如下 C 函数:
CGFloat myCFunction(CGFloat (callback)(CGFloat x, CGFloat y)) {
return callback(1.1, 2.2);
}
其中 callback
是一个函数指针,需要调用者自己实现,在 Swift 中,如果需要实现 callback
,供 myCFunction
调用的话,有以下写法,这里就会用到 @convention
:
let swiftCallback : @convention(c) (CGFloat, CGFloat) -> CGFloat = {
(x, y) -> CGFloat in
return x + y
}
let result = myCFunction( swiftCallback )
print(result) // 3.3
另外,还有更加简单地直接使用闭包的做法,这里没有用到 @convention
:
let result = myCFunction( {
(x, y) -> CGFloat in
return x + y
} )
print(result) // 3.3
与调用 C 的函数指针类似,要在 Swift 中调用一个含有 block 的 Objective-C 的方法时,需要使用 @convention(block)
定义 Swift 变量才能传入到 Objective-C 的方法中。当然也可以直接使用闭包,这里我们举一个动画方法的例子:
[UIView animateWithDuration:2 animations:^{
NSLog(@"start");
} completion:^(BOOL finished){
NSLog(@"completion");
}];
以上代码使用了 2 个 block,直接使用闭包转换成 Swift 代码:
UIView.animateWithDuration(2, animations: {
NSLog("start")
}, completion: {
(Bool completion) in
NSLog("completion")
})
等价使用 @convention(block)
的代码如下:
let animationsBlock : @convention(block) () -> () = {
NSLog("start")
}
let completionBlock : @convention(block) (Bool) -> () = {
(Bool completion) in
NSLog("start")
}
UIView.animateWithDuration(2, animations: animationsBlock, completion: completionBlock)
@convention(c)
? Swift blocks not working
Swift 中调用 OC block的问题。
在 Swift 2.0 当中使用 C 语言回调 :翻译组翻译好文,我也参与了校对。这篇文章重点是讲 Swift 如何处理调用 C 语言中的函数回调。
COPAQUEPOINTER 和 C CONVENTION :喵神的 tips,其中部分讲到了 C 语言函数指针的问题。非常通俗易懂。