Методы делегата в дочернем классе иногда не вызываются с помощью компилятора Swift 5 - PullRequest
12 голосов
/ 28 марта 2019

РЕДАКТИРОВАТЬ: Как sunshinejr указал здесь , это было исправлено и будет выпущено вместе со следующей версией Xcode / Swift.


Я видел много странного поведения после обновления Xcode 10.1 до Xcode 10.2, как с использованием кодовых баз Swift 4 и Swift 5.

Одна из проблем заключается в том, что на одном ViewController методы делегата ScrollView больше не вызываются. Упрощенная иерархия представления выглядит следующим образом:

| ScrollView (ParentScrollView)
| -- Stack View
| ---- ScrollView (ChildScrollView)
| ---- ScrollView (ChildScrollView)
| ---- ScrollView (ChildScrollView)

Он действует как представление с несколькими страницами: ParentScrollView можно прокручивать по горизонтали, ChildScrollView по вертикали.

ViewController является делегатом всех представлений Scrollview (заданных в раскадровке), но методы делегирования (например, scrollViewDidEndDecelerating) не вызываются при прокрутке любого из представлений (ParentScrollView или ChildScrollView). базовый класс из ViewController соответствует UIScrollViewDelegate.

Я пытался установить делегатов в коде, кроме того, что я понятия не имею, что я могу делать неправильно. Преобразование не изменило никакого кода в классе, но все работало хорошо перед обновлением. Я также не смог найти никаких изменений в жестах, делегатах или ScrollViews в целом в Swift 5 Примечания к выпуску .

Кажется, это ошибка компилятора Swift 5. Кроме того, иногда это работает, иногда нет - все без изменения кода или настроек проекта.

Почему это больше не работает? Кто-нибудь еще испытывал подобное поведение?

Ответы [ 6 ]

17 голосов
/ 28 марта 2019

РЕДАКТИРОВАТЬ: Как sunshinejr указал здесь , это было исправлено и будет выпущено вместе со следующей версией Xcode / Swift.


Я нашел проблему, вот как ее воспроизвести.

class A: UIViewController, UIScrollViewDelegate {
    // ...does not implement 'scrollViewDidEndDecelerating'
}

class B: A {
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        // Will not be called!
    }
}

Что работает:

class A: UIViewController, UIScrollViewDelegate {
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        // Probably empty
    }
}

class B: A {
    override func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        // Will be called!
    }
}

Компилятор, похоже, считает, что метод делегата не реализован, если базовый класс его не реализовал. Если только дочерний класс реализует его, он не может его найти.

Я до сих пор не могу объяснить, почему это поведение изменилось в Swift 5, но, по крайней мере, я нашел решение. Может быть, кто-то может дать дальнейшие идеи?

3 голосов
/ 17 апреля 2019

Похоже, что эта проблема существовала еще в 2016 году и была исправлена ​​в одной точке: https://bugs.swift.org/browse/SR-2919

1 голос
/ 29 мая 2019

Как указал Ян, это регрессия Swift 5.Это отслеживается на JIRA Свифта, а также на радаре (rdar: // problem / 49482328).Это также уже исправлено ( PR здесь ), но нам нужно дождаться следующего выпуска Xcode / Swift.

1 голос
/ 12 апреля 2019

Мы столкнулись с этим с помощью UITextViewDelegate

Другим обходным решением является добавление тега @objc к методу в суперклассе

1 голос
/ 06 апреля 2019

Мы испытываем ту же проблему после обновления с 4.2 (Xcode 10.1) до 5.0 (Xcode 10.2).В нашем случае это UITableViewDelegate.Родительский класс реализует методы, связанные с прокруткой, в UITableViewDelegate, однако методы, связанные с табличным представлением для этого делегата (такие как DidSelect RowAtIndex), реализованы в дочернем классе.Методы в дочернем классе были вызваны без проблем, прежде чем мы обновили XCode 10.2 с помощью Swift 5.

Переопределение методов делегата в дочернем классе, предложенное Яном Шлорфом, решило проблему.

0 голосов
/ 28 марта 2019

Поскольку все методы UIScrollViewDelegate являются опциональными, вы никогда не увидите ошибку от компилятора, если он думает, что вы не реализовали их, наиболее вероятно, что Apple изменила сигнатуру метода в Swift 5 (снова) и дляпо какой-то причине инструмент миграции не работал.
Проверьте имена методов вместе с UIScrollViewDelegate, обновленным до документации USwift 5, вы увидите, что, вероятно, ваши имена методов отличаются, просто исправьте их, и все должно работать снова.

...