Swift 4:扩展中无法重写非动态类声明(UITableView代理问题)
解决扩展中重写UITableView代理方法的报错问题
嘿,这个坑我之前踩过!你碰到的「Cannot override a non-dynamic class declaration from an extension」错误,本质是Swift的扩展设计初衷是给类添加新功能,而不是覆盖已有的方法——尤其是当父类的方法没有用dynamic修饰时,扩展根本没法重写它。
针对你的代码结构,给你两个可行的解决思路:
方案1:把重写方法放到子类主定义中(推荐)
这是最符合Swift设计规范的做法,直接在ChildViewController的类体里重写父类的代理方法,不要放到扩展里:
class ChildViewController: BaseTableViewController { // 直接在这里重写UITableView数据源/代理方法 override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { // 你的自定义行数逻辑 return 15 } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // 你的自定义cell配置逻辑 let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell cell.configure(with: yourDataArray[indexPath.row]) return cell } }
方案2:给父类方法添加dynamic修饰(不推荐,仅应急用)
如果你因为某些原因一定要用扩展重写,那需要修改父类BaseTableViewController,给要重写的代理方法加上dynamic关键字——这个关键字会让方法走Objective-C的动态运行时,从而允许扩展重写:
class BaseTableViewController: UITableViewDelegate, UITableViewDataSource { // 给需要被重写的方法添加dynamic修饰 dynamic func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { // 父类默认实现 return 0 } dynamic func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // 父类默认实现 return UITableViewCell(style: .default, reuseIdentifier: "DefaultCell") } }
之后你就能在ChildViewController的扩展里重写这些方法了,但要注意:dynamic会带来一定的性能开销,而且违背了Swift扩展的设计意图,所以非必要不建议用这个方案。
补充说明
Swift中,类本身的方法是存储在虚函数表(vtable)里的,支持动态重写;但扩展里的方法是静态绑定的,编译时就确定了调用逻辑,所以没法覆盖父类的非dynamic方法——这就是你报错的核心原因。
内容的提问来源于stack exchange,提问作者iOS
相关产品推荐
相关产品推荐

