swift inherited protocol method override

烈酒焚心 提交于 2019-12-12 02:45:53

问题


I was hoping this would work:

protocol Foo : UITableViewDelegate{
}

extension Foo{
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        print("ROW:\(indexPath.row)")
    }
}

class MyVC : UITableViewController, Foo{
   //...
}

No luck though, the method does not get called. Am I missing something, or is this genuinely not possible?

Also, there is no compiler warning/error, the method is just not being called, which some may consider a bug.


回答1:


I think this is because your are inheriting from UITableViewController which already implements UITableViewDelegate.

You can easily test this:

class MyVC: UITableViewController {
  func tableView(tableView tv: UITableView, 
                 didSelectRowAtIndexPath ip: NSIndexPath) {}
}

This will result in

error: overriding declaration requires an 'override' keyword

The compiler assumes the method is already implemented in the direct inheritance chain. Hence your default method from the protocol won't be picked.

Having said that, the variant below does not work either. Adding @objc to the protocol makes my swiftc segfault ...:

import UIKit

protocol Foo : UITableViewDelegate {
  func tableView(tableView: UITableView, didSelectRowAtIndexPath: NSIndexPath)
}

extension Foo {

  func tableView(tableView: UITableView,
                 didSelectRowAtIndexPath _: NSIndexPath)
  {
    print("abcXXX")
  }

}

class ViewController: UIViewController, UITableViewDataSource, Foo {

  override func loadView() {
    self.view = UITableView(frame: CGRect())
  }

  var tableView : UITableView { return self.view as! UITableView }

  override func viewDidLoad() {
    super.viewDidLoad()

    self.tableView.delegate   = self
    self.tableView.dataSource = self
    self.tableView.registerClass(UITableViewCell.self,
                                 forCellReuseIdentifier: "MyCell1")
  }

  func tableView(tableView: UITableView, numberOfRowsInSection _: Int) -> Int {
    return 3
  }

  func tableView(tableView: UITableView, cellForRowAtIndexPath ip: NSIndexPath)
        -> UITableViewCell
  {
    let cell = tableView
                 .dequeueReusableCellWithIdentifier("MyCell1", forIndexPath: ip)
    cell.textLabel?.text = "p[\(ip.row)]"
    return cell
  }
}

Hence I assume my answer is only 50% right. Presumably protocol extensions only work in static binding contexts, which excludes ObjC protocols?

Update: This seems to be the proper answer: Protocol-Oriented Programming with UIKit. The essence:

What we CAN'T do: Provide default implementations for Objective-C protocols.



来源:https://stackoverflow.com/questions/35686636/swift-inherited-protocol-method-override

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!