Swift中如何将字符串转换为函数名并传入#selector参数?
问题解答:字符串转Selector传给UITapGestureRecognizer是否可行?
首先直接给结论:你当前的写法完全不可行。因为#selector()是Swift的编译期语法糖,它要求传入明确的方法引用(比如#selector(handleTap(_:))),而不是字符串变量。编译器在编译阶段会校验这个方法是否存在、是否符合Selector的要求,但字符串是运行时才确定的值,编译器没法做这个校验,所以你的代码要么编译报错,要么运行时根本找不到目标方法。
那要实现“用字符串指定点击触发方法”的需求,得靠OC Runtime提供的NSSelectorFromString()方法——它能在运行时把字符串转换成合法的Selector。下面是修正后的代码示例:
func setFunctionWithTap(functionName: String) { // 重点:如果你的方法接收UITapGestureRecognizer参数,必须给字符串加冒号 let selectorString = "\(functionName):" guard let tapSelector = NSSelectorFromString(selectorString) else { print("找不到对应的方法名") return } // 额外做一层校验,避免运行时崩溃 guard responds(to: tapSelector) else { print("当前对象没有实现这个方法") return } let tap = UITapGestureRecognizer(target: self, action: tapSelector) // 这里假设你要把点击手势添加到某个视图,比如self.view self.view.addGestureRecognizer(tap) }
几个必须注意的细节:
- 给方法加@objc标记:Swift默认的方法不会暴露给OC Runtime,所以你要确保目标方法加上
@objc修饰符,比如:@objc func handleTap(_ tap: UITapGestureRecognizer) { print("点击事件触发啦") } - 别漏了方法名的冒号:如果你的方法带参数(比如接收UITapGestureRecognizer),Selector字符串必须包含末尾的冒号——这是OC Runtime的规则,冒号代表方法有一个参数。
- 尽量避免硬编码字符串:如果可以的话,先用
#selector()获取正确的方法字符串再传递,能减少拼写错误,比如:let methodString = NSStringFromSelector(#selector(handleTap(_:))) // 去掉冒号后传给你的方法 setFunctionWithTap(functionName: methodString.replacingOccurrences(of: ":", with: ""))
内容的提问来源于stack exchange,提问作者user9239212
相关产品推荐
相关产品推荐

