UIScrollView有一个委托属性,符合UIScrollViewDelegate
protocol UIScrollViewDelegate : NSObjectProtocol {
//...
}
class UIScrollView : UIView, NSCoding {
unowned(unsafe) var delegate: UIScrollViewDelegate?
//...
}
UICollectionView使用不同的类型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?
}
编译器给了我两个警告:
如何创建UIScrollView的子类并覆盖委托属性的类型(即使用自定义委托协议)?
答案 0 :(得分:18)
我认为重写继承属性是Objective-C中可能的,但在Swift中不是(至少目前)。我处理此问题的方法是将单独的委托声明为正确类型的计算属性,以获取并设置实际委托:
@objc protocol MyScrollViewDelegate : UIScrollViewDelegate, NSObjectProtocol {
func myHeight() -> CGFloat
// ...
}
class MyScrollView: UIScrollView {
var myDelegate: MyScrollViewDelegate? {
get { return self.delegate as? MyScrollViewDelegate }
set { self.delegate = newValue }
}
}
这样调用滚动视图委托的任何东西通常都可以工作,你可以在self.myDelegate
上调用你的特定委托方法,如下所示:
if let height = self.myDelegate?.myHeight() {
// ...
}
答案 1 :(得分:3)
我个人喜欢的方法不是直接子类化scrollview,而是创建一个包含并充当单独scrollview委托的UIView子类,然后在必要时将该scrollview的委托消息转发给UIView子类自己的委托。这还允许在滚动视图定义的区域之外添加自定义控件。与直接子类相比,它看起来有点不雅,但它至少可以避免令人不快的黑客攻击。
答案 2 :(得分:3)
这是一个用于更改Swift中覆盖属性类型的解决方案。当您需要扩展委托协议时,它尤其有用。
@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.2版进行测试。我希望它有所帮助。
答案 3 :(得分:3)
你可以这样做:
protocol ExtendedUIScrollViewDelegate: UIScrollViewDelegate {
func someNewFunction()
}
class CustomScrollView: UIScrollView {
weak var myDelegate: ExtendedScrollViewDelegate?
override weak var delegate: UIScrollViewDelegate? {
didSet {
myDelegate = delegate as? ExtendedScrollViewDelegate
}
}
}
希望这有帮助
答案 4 :(得分:1)
请考虑以下情况:
class BaseProp {}
class Base {
var prop: BaseProp
}
然后,如果您这样做:
class DerivedProp: BaseProp {}
class Derived: Base {
override var prop: DerivedProp
}
然后if会破坏子分类原则(即Liskov替代原则)。基本上,您正在执行的操作是将“ var prop”的范围从较宽的“ BaseProp”类型限制为较窄的“ DerivedProp”类型。这样的代码将是可行的,这是没有道理的:
class UnrelatedProp: BaseProp {}
let derived = Derived()
let base = derived as Base
base.prop = UnrelatedProp()
请注意,我们正在为属性分配UnrelatedProp实例,这对于我们实际使用的Derived实例没有意义。 ObjectiveC允许这种歧义,但是Swift不允许。
答案 5 :(得分:0)
您可以通过声明函数覆盖get和set方法,如:
func setDelegate(delegate:UITableViewDelegate?){
self.delegateInterceptor = delegate;
}
swift将属性编译为方法,如Objective-c那样。