我正在尝试在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
的子类。
答案 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
}
}