考虑通过Cocoapods包含的模块中的以下代码(我使用Eureka
,但问题与此无关):
open class FormViewController : UIViewController {
}
extension FormViewController : UITableViewDelegate {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// some default implementation
}
/// some other UITableViewDelegate methods follow, but _NOT_ willDisplayCell
}
我正在尝试子类化FormViewController
并为tableView(_:willDisplay:forRowAt:)
添加实现(这是UITableViewDelegate
中的可选方法)。此方法在原点FormViewController
中没有实现:
import UIKit
import Eureka
class MyViewController: FormViewController {
override func viewDidLoad() {
let tableView = UITableView(frame: self.view.bounds, style: .grouped)
tableView.delegate = self
tableView.dataSource = self
self.tableView = tableView
self.view.addSubview(self.tableView!)
super.viewDidLoad()
form = Form()
let section = Section()
section.append(EmailRow(){
$0.tag = "email"
$0.title = "Email"
})
form += [section]
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
print("NOT CALLED")
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("will be called")
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("GETS CALLED")
return super.tableView(tableView, cellForRowAt: indexPath)
}
}
/// somewhere else:
self.navigationController?.pushViewController(MyViewController(), animated: true)
使用此设置,将调用我的覆盖版tableView(_:cellForRowAt:)
(意味着tableView.delegate
已正确设置)。 tableView(_:willDisplay:forRowAt:)
将不会被调用。只要我在Eureka中添加一个空白实现,我就可以覆盖该方法。
问题:为什么Swift在超类中没有默认实现时不使用该方法?
答案 0 :(得分:3)
我自己也注意到了这个问题,这对我来说似乎是一个错误。你有两个选择。
首先,您可以在扩展中实现委托方法,并在子类中覆盖它。这将确保调用该方法。
extension FormViewController : UITableViewDelegate {
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
// you can leave the implementation blank if you want
}
}
class MyViewController: FormViewController {
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
print("CALLED!!")
}
}
其次,您可以使用pre-Swift 3表示法声明该方法,它将起作用。这部分对我来说也是一个错误(或同一个bug的所有部分)。我不推荐这个选项,因为它可能会在未来的Swift或Xcode版本中发生变化,并且通常会感觉很乱。
extension FormViewController : UITableViewDelegate {
// no willDisplayCell method
}
class MyViewController: FormViewController {
func tableView(_ tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
print("CALLED!!")
}
}
编辑:OP将UITableViewDelegate
方法放在扩展名中的事实并不会导致问题。即使类本身对委托进行了判决,问题仍然存在。
答案 1 :(得分:0)
在我的理解中,如果这是你的意思,那么在超类上定义的扩展不会在子类的级别上工作。您可以实现一种方法,但是您可以从子类调用超类来执行类中指定的某种默认行为。扩展
答案 2 :(得分:-1)
可能是控制器实例声明中的问题。
let myController: MyFormViewController = MyFormViewController()
tableView.delegate = myController
在这种情况下,一切都应该正常工作。但在另一个案例中
let myController: FormViewController = MyFormViewController()
tableView.delegate = myController
tableView(_:willDisplay:forRowAt:)
将不会被执行。