Переопределение свойства делегата UIScrollView в Swift (например, UICollectionView)
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?
}
компилятор дает мне два предупреждения:
- Свойство 'delegate' с типом 'MyScrollViewDelegate'? не может переопределить свойство с типом 'UIScrollViewDelegate?'
- "unowned" не может применяться к типу неклассов "MyScrollViewDelegate?"
Как я могу подклассифицировать UIScrollView и переопределить тип свойства делегата (т.е. использовать пользовательский протокол делегатов)?
Ответы
Ответ 1
Я думаю, что переопределение унаследованного свойства - это то, что возможно в 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() {
// ...
}
Ответ 2
Вот решение для изменения типа переопределяющих свойств в 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
Вы можете сделать следующее:
protocol ExtendedUIScrollViewDelegate: UIScrollViewDelegate {
func someNewFunction()
}
class CustomScrollView: UIScrollView {
weak var myDelegate: ExtendedScrollViewDelegate?
override weak var delegate: UIScrollViewDelegate? {
didSet {
myDelegate = delegate as? ExtendedScrollViewDelegate
}
}
}
Надеюсь, что это поможет
Ответ 4
Мой предпочтительный метод лично не относится к подзапросам scrollviews напрямую, но для создания подкласса UIView, содержащего и действующего как делегат для отдельного прокрутки, а затем пересылать эти сообщения делегатов scrollview в собственный делегат подкласса UIView, где это необходимо. Это также позволяет добавлять пользовательские элементы управления вне области, определенной в виде прокрутки. Это может показаться немного неэлегантным по сравнению с прямым подклассом, но он по крайней мере избегает неприятных хаков.
Ответ 5
Рассмотрим следующую ситуацию:
class BaseProp {}
class Base {
var prop: BaseProp
}
Тогда, если вы это сделаете:
class DerivedProp: BaseProp {}
class Derived: Base {
override var prop: DerivedProp
}
Тогда, если нарушат принципы подкласса (а именно, принцип замены Лискова). В основном то, что вы делаете, ограничивает объем "var prop" от более широкого типа "BaseProp" до более узкого типа "DerivedProp". Тогда такой тип кода был бы возможен, что не имеет смысла:
class UnrelatedProp: BaseProp {}
let derived = Derived()
let base = derived as Base
base.prop = UnrelatedProp()
Обратите внимание, что мы присваиваем этому экземпляру экземпляр UnrelatedProp, что не имеет смысла для экземпляра Derived, с которым мы фактически работаем. ObjectiveC допускает такую неоднозначность, но Swift этого не делает.
Ответ 6
Вы можете переопределить метод get и set с помощью функции declare, например:
func setDelegate(delegate:UITableViewDelegate?){
self.delegateInterceptor = delegate;
}
swift-компилятор свойство для метода как Objective-c делает.