iOS平台Swift中如何通过字符串调用类方法(含带参实现)
Swift 原生反射API(Mirror)仅支持属性读取、类型信息查询,不提供原生的方法动态调用能力,但可以通过两种成熟方案实现「通过字符串方法名调用带参方法」的需求,具体实现如下:
方案一:基于Objective-C Runtime实现(Apple平台推荐)
该方案适用于自定义类可以继承NSObject的场景,无需手动维护方法映射,使用成本最低,是iOS端最常用的实现方式。
- 前置要求:自定义类继承自
NSObject,需要被动态调用的方法添加@objc修饰,暴露给Objective-C runtime - 核心逻辑:通过
NSSelectorFromString将字符串方法名转换为Runtime识别的Selector,校验方法存在后通过perform系列方法完成调用 - 多参数适配:Selector命名遵循Objective-C方法签名规则,最多支持原生传递2个参数,更多参数可通过封装模型/字典、或
NSInvocation实现
代码示例:
import Foundation // 自定义类继承NSObject class CustomClass: NSObject { // 无参数方法 @objc func noParamMethod() { print("无参数方法调用成功") } // 带参数方法,可手动指定selector名称避免拼写错误 @objc(twoParamMethod:arg2:) func twoParamMethod(arg1: String, arg2: Int) { print("带参方法调用成功,参数1:\(arg1),参数2:\(arg2)") } } // 调用逻辑 let instance = CustomClass() // 调用无参数方法 let noParamSel = NSSelectorFromString("noParamMethod") if instance.responds(to: noParamSel) { instance.perform(noParamSel) } // 调用带2个参数的方法 let twoParamSel = NSSelectorFromString("twoParamMethod:arg2:") if instance.responds(to: twoParamSel) { instance.perform(twoParamSel, with: "测试字符串", with: NSNumber(value: 123)) }
注意:Swift基础类型(如Int、Bool、结构体等)传入
perform方法时需要桥接为Objective-C兼容的对象类型(如NSNumber、NSString等),否则会出现参数取值异常。
方案二:纯Swift手动映射实现(跨平台/无runtime依赖场景)
如果项目要求纯Swift实现、不希望依赖NSObject继承体系,可以通过手动维护「方法名-方法闭包」映射表的方式实现动态调用,该方案不依赖Runtime,可跨平台使用。
- 核心逻辑:在类内部维护一个字典,key为字符串形式的方法名,value为对应方法的闭包引用,对外提供统一的调用入口,根据传入的方法名查找对应闭包执行
- 多参数适配:统一用
[Any]类型数组承载所有参数,在具体方法内部做参数个数、类型校验
代码示例:
class PureSwiftClass { // 方法映射表 private lazy var methodMap: [String: ([Any]) -> Void] = [ "noParamMethod": self.noParamMethod, "singleParamMethod": self.singleParamMethod(params:), "multiParamMethod": self.multiParamMethod(params:) ] // 统一调用入口 func invoke(methodName: String, params: [Any] = []) { guard let targetMethod = methodMap[methodName] else { print("错误:不存在名为\(methodName)的方法") return } targetMethod(params) } // 具体业务方法 private func noParamMethod(params: [Any]) { print("纯Swift无参数方法调用成功") } private func singleParamMethod(params: [Any]) { guard let content = params.first as? String else { print("错误:单参数方法参数类型不匹配") return } print("纯Swift单参数方法调用成功,参数:\(content)") } private func multiParamMethod(params: [Any]) { guard params.count >= 2, let content = params[0] as? String, let count = params[1] as? Int else { print("错误:多参数方法参数个数/类型不匹配") return } print("纯Swift多参数方法调用成功,参数1:\(content),参数2:\(count)") } } // 调用逻辑 let swiftInstance = PureSwiftClass() swiftInstance.invoke(methodName: "noParamMethod") swiftInstance.invoke(methodName: "singleParamMethod", params: ["入参测试"]) swiftInstance.invoke(methodName: "multiParamMethod", params: ["多参测试", 456])
该方案的优缺点:
- 优点:无NSObject继承要求,不依赖Objective-C runtime,支持所有Swift类型,可在非Apple平台运行
- 缺点:新增可动态调用的方法时需要手动更新映射表,参数类型安全由开发者自行校验
内容的提问来源于stack exchange,提问作者Emanuele Mele
相关产品推荐
相关产品推荐

