Делегат UIScrollView как реализация протокола по умолчанию

#swift #uiscrollview #uicollectionview #swift-protocols

#быстрый #uiscrollview uiscrollview #uicollectionview uicollectionview #swift-протоколы

Вопрос:

Я пытаюсь реализовать реализацию по умолчанию для UIScrollViewDelegate метода:

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>)

используя protocol .

Если я помещаю этот метод внутри класса, он вызывается; однако, если я пытаюсь использовать в качестве реализации по умолчанию via protocol , он никогда не вызывается.

Код:

 protocol DefaultScrollViewEndDragging {
    func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>)
}

extension DefaultScrollViewEndDragging {
    func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        print("scrollViewWillEndDragging is called")
        // THIS IS NEVER CALLED
    }
}

class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, DefaultScrollViewEndDragging {

    @IBOutlet weak var collectionView: UICollectionView!

    override func viewDidLoad() {
        super.viewDidLoad()
        collectionView.dataSource = self
        collectionView.delegate = self
        collectionView!.register(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 5
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath)
        print("Cell (indexPath.row)")
        cell.contentView.backgroundColor = .orange
        return cell
    }
}
 

Что я делаю не так?

Ответ №1:

Я думаю, вы ищете что-то вроде этого

 protocol DefaultScrollViewEndDragging : UIScrollViewDelegate {
    func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>)
}

extension DefaultScrollViewEndDragging {
    func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        print("scrollViewWillEndDragging is called")
        // THIS IS NEVER CALLED
    }
}
 

К сожалению, расширения протокола недоступны Obj-C. поэтому он не вызывается scrollViewWillEndDragging

Из заметки

Опять же, единственным исключением из этого правила являются расширения протокола. В отличие от любой другой конструкции в языке, методы расширения протокола отправляются статически в ситуации, когда виртуальная отправка приведет к другим результатам. Никакая ошибка компилятора не предотвращает это несоответствие. https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/001707.html

Комментарии:

1. @user1107173 К сожалению, расширения протокола недоступны Obj-C. поэтому он не вызывается scrollViewWillEndDragging

2. @user1107173 пожалуйста, проверьте мой обновленный ответ. если у вас все еще есть путаница в какой-либо части, дайте мне знать.

Ответ №2:

Правильный код

 class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UIScrollViewDelegate {

@IBOutlet weak var collectionView: UICollectionView!

override func viewDidLoad() {
    super.viewDidLoad()
    collectionView.dataSource = self
    collectionView.delegate = self
    collectionView!.register(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 5
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath)
    print("Cell (indexPath.row)")
    cell.contentView.backgroundColor = .orange
    return cell
}
//MARK: scrollview Delegate Method
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
    print("scrollViewWillEndDragging is called")
}
 

}

Комментарии:

1. Я упоминал в своем вопросе, что это работает таким образом. Я пытаюсь использовать его в качестве реализации по умолчанию.

2. что вы хотите сделать? это не будет работать так, как вы хотите. вы должны запустить метод протокола с помощью delegate.method() куда-нибудь, а затем он автоматически вызовет место, где вы реализуете этот метод. пожалуйста, отредактируйте свой запрос подробно, чего вы хотите достичь.