iOS知识小集之Swift闭包作为Objective-C方法参数

Swift闭包作为Objective-C方法参数


Swift开发时,有时我们需要调用带有Block参数的Objective-C方法,比如,我们通过perform(_:with:afterDelay:inModes:)来在特定的Runloop模式下运行某selector,如下所示,doAnimation方法接收一个OptionalBlock,注意,该方法标注了@objc,所以是Objective-C方法,animationBlock参数为Objective-CBlock,那么我们怎么将SwiftClosure转化为Block呢,方法就是使用@convention(block)来声明兼容Objective-C BlockClosure,如下[1]所示:

1
2
3
4
5
6
7
8
9
10
11
12
class LocationMessageCell: UICollectionViewCell {
func callSEL() {
let block: @convention(block) (UIImageView) -> Void = { _ in // [1]
....
}
self.perform(#selector(LocationMessageCell.doAnimation(with:)), with: block, afterDelay: 0, inModes: [.defaultRunLoopMode])
}

@objc private func doAnimation(with animationBlock: ((UIImageView) -> Void)!) {
....
}
}

除了显式的用@convention(block)来声明,我们也可以直接使用闭包,如:

1
2
3
UIView.animate(withDuration: 0.1, animations: {
...
})

注意,之所以我没有在之前的例子进行修改,是因为func perform(_ aSelector: Selector, with anArgument: Any?, afterDelay delay: TimeInterval, inModes modes: [RunLoopMode])anArgument参数类型为Any?,编译器没有进行自动转换,这种情况只能显式的声明@convention(block)

参考


  1. https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html