是一种语法糖, 有两种实现方式, 输入类型和输出类型都可定义。 不能添加到扩展, 只能在类型主定义中
请看下面使用案例:
@dynamicCallable
struct Greeter {
// 还可以添加正常的属性和方法
func greet(name: String) {
print(name)
}
// 方法1 和方法2 定义不冲突,但是调用会发生模糊不清
//func dynamicallyCall(withArguments args: [Int]) {
// for n in args {
// print("num = \(n)")
// }
//}
// 方法2
func dynamicallyCall(withArguments args: [Int]) -> Double {
for num in args {
return Double(num) * 2
}
return 0.0
}
// 方法3
func dynamicallyCall(withArguments args: [String]) {
for str in args {
print("str = \(str)")
}
}
// 方法4
func dynamicallyCall(withKeywordArguments args: KeyValuePairs<String, String>) {
for (key, value) in args {
print("key = \(key)")
print("Hi, \(value).")
}
}
}
更多的写法
对于第一个方法(没有参数标签),您可以使用任何符合ExpressibleByArrayLiteral的任何方法,如数组、数组切片和集;对于第二种方法(带有参数标签),您可以使用任何符合ExpressibleByDictionaryLiteral文本,如字典和键值对。
使用集合
func dynamicallyCall(withArguments args: Set<Int>) {
for n in args {
print("num = \(n)")
}
}
使用字典 (此时, 调用时标签字段不能重复)
func dynamicallyCall(withKeywordArguments args: [String: String] ) {
for (key, value) in args {
print("key = \(key)")
print("Hi, \(value).")
}
}
调用
一种不带带标签的调用, 另一种带标签的。
let gretter = Greeter()
gretter(name: "Tyler")
gretter(person: "Bob", name2: "Tim", person: "Nancy")
let d = gretter(1, 2, 3)
gretter(name: "Hello")
// 调用方法1
gretter(1, 2, 3)
// 调用方法2
let d = gretter(1, 2, 3)
// 调用的 方法3
greeter("Jack")
// 调用的 方法4, person标签传了两次, 且后面的没覆盖前面的person
gretter(person: "Bob", name2: "Tim", person: "Nancy")
注意点
- 在不实现 dynamicallyCall(withArguments 方法时, 去调用dynamicallyCall(withKeywordArguments 也可不用传参数,此时的 key 为空
greeter("Jack")
KeyValuePairs
具有的特点
- 您的密钥不需要符合Hashable.
- 您可以使用重复的键添加项。(不会覆盖自定中添加的值)
- 添加项的顺序将保留。(是DictionAry变有序)