Xcode 9中‘Unrecognised selector’报错及TableView点击触发方法实现
解决Xcode 9中TableView点击触发方法时的「Unrecognised selector sent to instance」错误
我来帮你搞定这个问题——你遇到的错误本质是用字符串存储方法名的方式存在类型安全隐患,且Swift方法默认不暴露给Objective-C,导致运行时找不到对应的方法。下面给你两种解决方案,优先推荐更符合Swift最佳实践的方式:
方案一:用闭包(Closure)替代字符串方法名(推荐)
这种方式完全避免了selector相关的运行时错误,类型更安全,是Swift的首选写法。
1. 修改LeftMenuItem的定义
把原来存储方法名字符串的属性换成闭包类型:
struct LeftMenuItem { let imageName: String let cellLabel: String let action: () -> Void // 无参无返回值的闭包,对应你的方法类型 }
2. 填充菜单数据时直接绑定方法
在populateLeftMenuData里,直接把视图控制器的方法作为闭包传入:
var menuItems = [LeftMenuItem]() func populateLeftMenuData() { // 绑定home方法 let homeItem = LeftMenuItem(imageName: "flagIcon", cellLabel: "Home", action: home) menuItems.append(homeItem) // 绑定logout方法 let logoutItem = LeftMenuItem(imageName: "flagIcon", cellLabel: "Logout", action: logout) menuItems.append(logoutItem) } // 确保你的方法是正常定义的(不需要额外加@objc) func home() { // 这里写Home按钮的逻辑 print("Home clicked!") } func logout() { // 这里写Logout按钮的逻辑 print("Logout clicked!") }
3. TableView点击时执行闭包
在tableView(_:didSelectRowAt:)方法里,直接调用选中项的闭包即可:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) let selectedItem = menuItems[indexPath.row] selectedItem.action() // 直接执行绑定的方法,不会有找不到selector的问题 }
方案二:修复Selector调用方式(兼容老代码)
如果你坚持要用字符串存储方法名的方式,需要解决Objective-C兼容性问题:
1. 给视图控制器的方法添加@objc标记
Swift方法默认不会暴露给Objective-C,所以必须加@objc让系统能通过selector找到它:
@objc func home() { print("Home clicked!") } @objc func logout() { print("Logout clicked!") }
2. 安全调用Selector
在点击cell时,先检查当前实例是否响应这个selector,再执行:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) let selectedItem = menuItems[indexPath.row] // 安全创建Selector并检查响应性 guard let targetSelector = Selector(selectedItem.method) else { print("无效的方法名:\(selectedItem.method)") return } if self.responds(to: targetSelector) { self.perform(targetSelector) } else { print("当前实例不响应方法:\(targetSelector)") } }
为什么原来的代码会出错?
- Swift的方法默认不会暴露给Objective-C运行时,所以用
Selector查找时找不到对应的方法; - 用字符串存储方法名容易出现拼写错误,或者方法签名修改后字符串没同步更新,导致运行时匹配失败。
内容的提问来源于stack exchange,提问作者aqsa arshad
相关产品推荐
相关产品推荐

