[SwiftUI 开发] @dynamicCallable 与 callAsFunction:将类型实例作为函数调用

在 Swift 中,@dynamicCallable 和 callAsFunction 提供了两种将类型实例作为函数调用的方式。

1. callAsFunction

对于 callAsFunction,只需实现名为 callAsFunction 的方法,参数和返回值可自行任意定义。

例如,考虑一个ShapeCalculator结构体:

Swift 复制代码
struct ShapeCalculator {
    func callAsFunction(length: Int, width: Double) -> Double {
        return Double(length) * width
    }
    func callAsFunction(radius: Double) -> Double {
        return 3.14 * radius * radius
    }
    func callAsFunction(side: Double) -> Double {
        return side * side
    }
}
使用示例
Swift 复制代码
func runTest() -> Void {
    let calculator = ShapeCalculator()
    print("Area: \(calculator(length: 5, width: 3.0))")
    print("Area: \(calculator(radius: 2.0))")
    print("Area: \(calculator(side: 4.0))")
}
输出结果如下:
Swift 复制代码
Area: 15.0
Area: 12.56
Area: 16.0

2:@dynamicCallable

当使用 @dynamicCallable 时,需要将此属性应用于类、结构、枚举或协议,使其类型的实例可被视为可调用函数。这要求必须实现dynamicallyCall(withArguments:)dynamicallyCall(withKeywordArguments:)其中一个或两个方法。

例如,我们创建一个StringManipulator结构体:

Swift 复制代码
@dynamicCallable struct StringManipulator {
    func dynamicallyCall(withArguments args: [String]) -> String {
        var result = ""
        for string in args {
            result += string.uppercased()
        }
        return result
    }
    func dynamicallyCall(withKeywordArguments pairs: KeyValuePairs<String, String>) -> String {
        var result = ""
        for (key, value) in pairs {
            result += "\(key): \(value.uppercased())\n"
        }
        return result
    }
}
使用示例
Swift 复制代码
func runTest() -> Void {
    let manipulator = StringManipulator()
    print("Result: \(manipulator("hello", "world"))")
    print("Result: \(manipulator(name: "John", age: "30"))")
}
输出结果为:
Swift 复制代码
Result: HELLO WORLD
Result: NAME: JOHN
AGE: 30

两者的区别

1. 参数类型要求

@dynamicCallable实现的方法调用,参数类型必须一致, 参数数量可以不一样

callAsFunction 参数类型可以不一致, 参数数量固定的

2. 方法命名要求

@dynamicCallable必须实现一个名为dynamicallyCall的方法,参数标签名称必须是withArguments或withKeywordArguments;callAsFunction必须实现一个名为callAsFunction的方法,并且参数标签可以自定义,因此callAsFunction具有更灵活的参数标签命名

3. 相同点

两者实现的方法都支持方法重载,但对于@dynamicCallable,重载方法的参数标签必须是withArguments或withKeywordArguments

相关推荐
帅次4 小时前
Android 17 开发者实战:核心更新与应用场景落地指南
android·java·ios·android studio·iphone·android jetpack·webview
人月神话Lee5 小时前
【图像处理】Core Image 与 GPU 渲染管线——让滤镜飞起来
ios·ai编程·图像识别
sakiko_7 小时前
Swift学习笔记34-MVC架构,SwiftUI与UIkit混编练习
笔记·学习·swiftui·mvc·swift
帅次12 小时前
讯飞与腾讯云:Android 实时语音识别服务对比选择
android·ios·微信小程序·小程序·android studio·android runtime
择势13 小时前
用一套View代码,同时支持RTL和LTR布局混合排版
ios
游戏开发爱好者814 小时前
iOS开发工具推荐:Xcode、AppCode、SwiftLint使用心得与效率提升
ide·vscode·macos·ios·个人开发·xcode·敏捷流程
2501_9159090615 小时前
深入理解HTTPS中间人抓包技术原理与实战指南
网络协议·http·ios·小程序·https·uni-app·iphone
sakiko_15 小时前
Swift学习笔记35-本地化
笔记·学习·swift
择势1 天前
基于声网 Agora RTM + RTC SDK 实现 iOS 语音聊天室 —— 常见问题汇总 & 解决方案手册
ios
择势1 天前
基于声网 Agora RTM + RTC SDK 实现 iOS 语音聊天室(进阶封装)
ios