使用扩展名

时间:2018-07-30 13:42:23

标签: ios swift uitableview

我正在尝试在UITableView中的contentSize更新时,contentSize通知其代理人UITableView

因此,我在contentSize的{​​{1}}中添加了属性观察器,该属性观察器调用了名为UITableview的委托方法。

然后我扩展了tableView(_ tableView: didUpdateContentSize contentSize:),以便符合UITableViewDelegate的{​​{1}}可以为其用例声明UIViewController

UITableViewDelegate

但是在扩展名tableView(_ tableView: didUpdateContentSize contentSize:)中,它会收到错误“函数声明正文中的预期'{'”

是否没有方法声明就无法扩展现有协议(例如extension UITableView { override open var contentSize: CGSize { didSet { self.delegate?.tableView(self, didUpdateContentSize: contentSize) } } } extension UITableViewDelegate { func tableView(_ tableView: UITableView, didUpdateContentSize contentSize: CGSize) // Error: "Expected '{' in body of function declaration" } 委托协议)?

我想实现我的意图而没有成为UITableViewDelegate的子类。

3 个答案:

答案 0 :(得分:2)

此部分已经无效:

extension UITableView {
    override open var contentSize: CGSize {
        didSet {
            self.delegate?.tableView(self, didUpdateContentSize: contentSize)
        }
    }
}

不允许覆盖扩展名中的方法/属性。有时您可能会忽略它,但这是未定义的行为(我很惊讶Swift编译器没有抛出错误)。无法保证将实际调用此实现。有可能;可能不是;有时可能是。有关更多详细信息,请参见Overriding methods in Swift extensions。 (这是NSObject子类的事实,可能是为什么它没有失败的原因,但这并不能使它正常。这在ObjC中也不安全。)

实现此目的的正确方法是让委托使用NSKeyValueObserving来观察tableView的contentView

答案 1 :(得分:1)

如果您对所有TableView绝对需要默认行为,则可以执行以下操作:

public protocol ContentSizeProtocol: UITableViewDelegate {
    func tableView(_ tableView: UITableView, didUpdateContentSize contentSize: CGSize)
}

public extension UITableView {
    override open var contentSize: CGSize {
        didSet {
            guard let delegate = delegate as? ContentSizeDelegate else {
                return
            }
            delegate.tableView(self, didUpdateContentSize: contentSize)
        }
    }
} 

您只需要确保拥有的任何VC都实现了ContentSizeDelegate,然后您执行tableView.delegate = viewControllerThatImplementsContentSizeDelegate

答案 2 :(得分:1)

您不能通过向现有协议添加新要求(即方法)来扩展现有协议。但是,您可以派生现有协议,然后向该协议添加新方法:

protocol MyTableViewDelegate: UITableViewDelegate {
    optional func tableView(_ tableView: UITableView, didUpdateContentSize contentSize: CGSize)
}

,然后在表格视图中调用此新方法:

class MyTableView: UITableView {
    override open var contentSize: CGSize {
        didSet {
            (self.delegate as? MyTableViewDelegate)?.tableView?(self, didUpdateContentSize: contentSize)
        }
    }
}

请注意,上面的代码将UITableView子类化而不是对其进行扩展,因为不建议使用扩展名中的重写方法(尽管如果您确实希望可以在UITableView上的扩展名中添加代码)。这应该不会引起太多麻烦,因为可以在情节提要/ xibs /代码中轻松更改表视图类。

然后,您可以使您的视图控制器符合扩展的委托,那么您应该很好:

extension MyViewController: MyTableViewDelegate {
    func tableView(_ tableView: UITableView, didUpdateContentSize contentSize: CGSize) {
        // do your stuff
    }
}