这里每天分享一个 iOS 的新知识,快来关注我吧
@dynamicCallable
@dynamicCallable 是 Swift 5.0 中新增的一个属性,它可以让 struct、enum、protocol 和 class也拥有像函数一样可以被调用的能力。
我们都知道 swift 在和 C 语言、OC 交互的时候很容易,但是和其他语言交互就不那么容易了,这个特性其目的就是为了使 Swift 代码能和类似 Python、JavaScript、Perl 和 Ruby 等动态语言之间交互。
@dynamicCallable 的使用
为 struct 或 class 添加 @dynamicCallable 属性:
@dynamicCallable
struct Math {
func dynamicallyCall(withArguments args: [Int]) -> Int {
print(args)
// 实现调用逻辑
return 0
}
func dynamicallyCall(withKeywordArguments args: KeyValuePairs<String, Int>) -> Double {
print(args)
// 实现调用逻辑
return 0
}
}
标记 @dynamicCallable 之后,dynamicallyCall(withArguments:) 方法和 dynamicallyCall(withKeywordArguments:) 方法至少实现其中一个,或者两个都实现。
之后就可以像调用函数一样调用 Math:
let m = Math()
let result1 = m(1, 2)
let result2 = m(a: 1, b: 2)
当执行 m(1, 2) 方法时会调用 m 的 dynamicallyCall(withArguments:) 方法,打印 [1, 2]。
当执行 m(a: 1, b: 2) 方法时会调用 m 的 dynamicallyCall(withKeywordArguments:) 方法,打印 ["a": 1, "b": 2]。
dynamicCallable 的原理
@dynamicCallable 原理是 Swift 编译器会将调用转换成对应的 dynamicallyCall 方法的调用。
当调用 m(1, 2) 时,编译器底层会转换成:
m.dynamicallyCall(withArguments: [1, 2])
当调用 m(a: 1, b: 2) 时,编译器底层会转换成:
m.dynamicallyCall(withKeywordArguments: ["a": 1, "b": 2])
因此我们只需要实现对应的 dynamicallyCall 方法即可拦截所有调用。
dynamicCallable 的用途
@dynamicCallable 使得 struct 和 class 可以像函数一样被调用,一些使用场景包括:
-
创建自定义操作符(运算符重载)
-
方法的动态调用,可以做一些特殊情况的保底逻辑
-
实现函数式编程
-
结合 @dynamicMemberLookup 关键字可以和其他动态语言交互
总体来说,@dynamicCallable 为 Swift 增加了表达能力,使语法更加灵活。
本文同步自微信公众号 “iOS新知”,每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!