web-dev-qa-db-fra.com

Les méthodes déléguées dans la classe enfant ne sont parfois pas appelées avec le compilateur Swift 5

EDIT: Comme sunshinejr l'a souligné ici , cela a été corrigé et sera publié avec la prochaine version Xcode/Swift.


J'ai vu beaucoup de comportements étranges après la mise à jour de Xcode 10.1 vers Xcode 10.2, à la fois avec Swift 4 et Swift 5 bases de code).

L'un des problèmes est que sur un ViewController les méthodes déléguées ScrollView ne sont plus appelées. La hiérarchie des vues simplifiées est la suivante:

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

Il agit comme une vue avec plusieurs pages: ParentScrollView peut défiler horizontalement, les ChildScrollViews verticalement.

Le ViewController est le délégué de toutes les vues de défilement (définies dans Storyboard), mais les méthodes de délégué (comme scrollViewDidEndDecelerating) ne sont pas appelées lors du défilement des vues (ParentScrollView ou ChildScrollView). La classe de base de ViewController est conforme à UIScrollViewDelegate.

J'ai essayé de mettre les délégués en code, à part ça, je n'ai aucune idée de ce que je pourrais faire de mal. La conversion n'a changé aucun code dans la classe, mais tout a bien fonctionné avant la mise à jour. Je n'ai également trouvé aucune modification des gestes, des délégués ou des ScrollViews en général dans les Swift 5 Release Notes .

Cela semble être un bogue avec le compilateur Swift 5. De plus, parfois cela fonctionne, parfois non - le tout sans changer le code ou les paramètres du projet.

Pourquoi ça ne marche plus? Quelqu'un d'autre a-t-il connu un comportement similaire?

16
Ginger Apps

EDIT: Comme sunshinejr l'a souligné ici , cela a été corrigé et sera publié avec la prochaine version Xcode/Swift.


J'ai trouvé le problème, voici comment le reproduire.

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

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

Qu'est-ce qui fonctionne:

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

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

Le compilateur semble penser qu'une méthode déléguée n'est pas implémentée si la classe de base ne l'a pas implémentée. Si seule la classe enfant l'implémente, elle ne le trouve pas.

Je ne peux toujours pas expliquer pourquoi ce comportement a changé avec Swift 5, mais au moins j'ai trouvé une solution. Peut-être que quelqu'un peut donner des informations supplémentaires?

20
Ginger Apps

Nous avons rencontré cela avec un UITextViewDelegate

Une autre solution consiste à ajouter le @objc tag vers la méthode dans la superclasse

4
ndis1

Comme l'a souligné Jan, il s'agit d'une régression Swift 5. Elle est suivie sur JIRA de Swift ainsi que sur le radar ( rdar: // problem/49482328) .Ceci est également déjà corrigé ( PR ici ) mais nous devons attendre la prochaine version de Xcode/Swift.

Edit: Depuis Xcode 10.3, nous avons observé que le bug est corrigé, mais nous surveillons toujours s'il est corrigé pour de bon.

3
sunshinejr

Il semble que ce problème existait également en 2016 et a été résolu à un moment donné: https://bugs.Swift.org/browse/SR-2919

3
eito

J'ai rencontré le même problème uniquement avec le schéma de publication après la mise à niveau vers Xcode 10.2. J'ai également testé Xcode 10.3 et c'est exactement le même comportement.

Pour ceux qui ne veulent pas ajouter @objc partout dans votre implémentation de délégué.

La solution rapide consiste à désactiver l'optimisation du compilateur Swift 5 dans les paramètres de génération:

enter image description here

Pour ceux qui ont déjà mis à niveau vers Xcode 10.3, il semble que cette option de paramètres de construction ne soit plus visible, mais vous pouvez toujours la modifier directement via le fichier pbxproj de votre projet et elle devrait apparaître dans l'interface utilisateur de xcode par la suite. Swift_COMPILATION_MODE = singlefile;

enter image description here

1
Gomino

Étant donné que toutes les méthodes UIScrollViewDelegate sont optionnelles, vous ne verrez jamais d'erreur du compilateur s'il pense que vous ne les avez pas implémentées, ce qui se passe probablement est que Apple méthode modifiée signature en Swift 5 (encore) et pour une raison quelconque, l'outil de migration n'a pas fonctionné.
Vérifiez les noms des méthodes avec UIScrollViewDelegate mis à jour dans la documentation USwift 5, vous verrez que probablement les noms de vos méthodes sont différents, corrigez-les simplement et tout devrait fonctionner à nouveau.

0
Andrea