在Swift中重写UIScrollView的委托属性(如UICollectionView)

UIScrollView有一个符合UIScrollViewDelegate的委托属性

protocol UIScrollViewDelegate : NSObjectProtocol { //... } class UIScrollView : UIView, NSCoding { unowned(unsafe) var delegate: UIScrollViewDelegate? //... } 

UICollectionView用一个不同types的UICollectionViewDelegate覆盖这个属性

 protocol UICollectionViewDelegate : UIScrollViewDelegate, NSObjectProtocol { //... } class UICollectionView : UIScrollView { unowned(unsafe) var delegate: UICollectionViewDelegate? //... } 

当我尝试用我的协议覆盖UIScrollViews委托,如下所示:

 protocol MyScrollViewDelegate : UIScrollViewDelegate, NSObjectProtocol { //... } class MyScrollView: UIScrollView { unowned(unsafe) var delegate: MyScrollViewDelegate? } 

编译器给了我两个警告:

  • 属性“委托”与types“MyScrollViewDelegate?” 不能覆盖types为“UIScrollViewDelegate?”的属性
  • “无主”不能应用于非types的“MyScrollViewDelegate?”

我如何inheritanceUIScrollView并覆盖委托属性的types(即使用自定义委托协议)?

我认为重写一个inheritance的属性是在Objective-C中可能的,但在Swift中不是(至less现在)。 我处理这个的方式是声明一个单独的委托作为正确types的计算属性,获取并设置实际的委托:

 @objc protocol MyScrollViewDelegate : UIScrollViewDelegate, NSObjectProtocol { func myHeight() -> CGFloat // ... } class MyScrollView: UIScrollView { var myDelegate: MyScrollViewDelegate? { get { return self.delegate as? MyScrollViewDelegate } set { self.delegate = newValue } } } 

通过这种方式,任何调用scroll view委托的东西仍然可以正常工作,您可以在self.myDelegate上调用您特定的委托方法,如下所示:

 if let height = self.myDelegate?.myHeight() { // ... } 

这是一个解决scheme,用于改变Swift中重载属性的types。 当您需要扩展委托的协议时,它特别有用。

 @objc protocol ExtendedUIScrollViewDelegate: UIScrollViewDelegate { func someNewFunction() } class CustomScrollView: UIScrollView { weak var delegateInterceptor: ExtendedScrollViewDelegate? override var delegate: UIScrollViewDelegate! { didSet { if let newValue = delegate { let castedDelegate = unsafeBitCast(delegate, ExtendedScrollViewDelegate.self) delegateInterceptor = castedDelegate } else { delegateInterceptor = nil } } } } 

这工作与Swift版本1.2testing。 我希望它有帮助。

我个人最喜欢的方法不是直接子类滚动视图,而是创build一个UIView子类,并作为单独的滚动视图的代理,然后将该滚动视图的委托消息转发到UIView子类自己的代理(如有必要)。 这也允许在由滚动视图定义的区域之外添加自定义控件。 与直接子类相比,它可能看起来有点不雅,但至less避免了不愉快的攻击。

你可以这样做:

 protocol ExtendedUIScrollViewDelegate: UIScrollViewDelegate { func someNewFunction() } class CustomScrollView: UIScrollView { weak var myDelegate: ExtendedScrollViewDelegate? override weak var delegate: UIScrollViewDelegate? { didSet { myDelegate = delegate as? ExtendedScrollViewDelegate } } } 

希望这可以帮助

您可以通过声明函数来覆盖get和set方法,如:

 func setDelegate(delegate:UITableViewDelegate?){ self.delegateInterceptor = delegate; } 

swift将属性编译为Objective-c的方法。