Swift 5 中引入了一个新的语法@dynamicCallable
(动态可调用)。使用@dynamicCallable
标记了目标以后(类、结构体、枚举、协议),实现dynamicallyCall
方法后,目标可以像调用函数一样使用。
@dynamicCallable
:标记类、结构体、枚举、协议dynamicallyCall
:实现该方法,可以像调用函数一样去调用类型,需要指定接收的参数和参数类型。// 标记
@dynamicCallable
struct Person {
// 实现方法一
func dynamicallyCall(withArguments: [String]) {
for item in withArguments {
print(item)
}
}
// 实现方法二
func dynamicallyCall(withKeywordArguments: KeyValuePairs<String, String>){
for (key, value) in withKeywordArguments {
print("\(key) --- \(value)")
}
}
}
let p = Person()
p("zhangsan")
// 等于 p.dynamicallyCall(withArguments: ["zhangsan"])
p("zhangsan", "20", "男")
// 等于 p.dynamicallyCall(withArguments: ["zhangsan", "20", "男"])
p(name: "zhangsan")
// 等于 p.dynamicallyCall(withKeywordArguments: ["name": "zhangsan"])
p(name: "zhangsan", age:"20", sex: "男")
// 等于 p.dynamicallyCall(withKeywordArguments: ["name": "zhangsan", "age": "20", "sex": "男"])
解读
@dynamicMemberLookup
后,必须实现dynamicallyCall(withArguments:)
和dynamicallyCall(withKeywordArguments:)
两个方法中的至少一个,否则编译器会报错。dynamicallyCall(withArguments:)
[String]
。dynamicallyCall(withKeywordArguments:)
KeyValuePairs
,暂时可以把它当成字典来用,主要改变的是value
的类型,如上例中为String
。dynamicallyCall(withKeywordArguments:)
但没有实现dynamicallyCall(withArguments:)
,也可以在没有参数标签的情况下调用dynamicallyCall(withKeywordArguments:)
或dynamicallyCall(withArguments:)
时标记为throw
,则调用该类型也将被抛出throw
@dynamicCallable
,只能添加到主要类型上在 Swift 5 中,之前的DictionaryLiteral
类型被重命为KeyValuePairs
。
public init(dictionaryLiteral elements: (Key, Value)...)
,其中后面的那一串就是DictionaryLiteral
,即KeyValuePairs
。let dic = Dictionary(dictionaryLiteral: ("name","zhangsan"), ("age","20"),("sex","男"))
print(dic["name"])
KeyValuePairs
只有一个构造函数// 构造函数
public init(dictionaryLiteral elements: (Key, Value)...)
// 构造一个person
let person: KeyValuePairs = KeyValuePairs(dictionaryLiteral: ("name","zhangsan"), ("age","20"),("sex","男"))
Dictionary
提供的快速键查找,请使用KeyValuePairs
类型以获取替代方案。 Swift 目前可以与 C、OC 交互。但如 Python 、 JavaScript 等则不行,如果 Swift 能够调用 Python 、JavaScript 等语言,那么毫无疑问会极大的拓展的 Swift 的边界。
想要实现这一点,@dynamicMemberLookup
、 @dynamicCallable
双剑合璧或可实现。首先通过@dynamicMemberLookup
动态的返回一个函数,再通过@dynamicCallable
来调用。