2017-05-08 3 views
5

J'ai trouvé ce problème cible UIBarButtonItem inconsciemment lors de l'utilisation de l'initialisation var paresseux.iOS paresseux var UIBarButtonItem cible problème

class ViewController: UIViewController { 
    lazy var barButtonItem1 = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(action1)) 
    lazy var barButtonItem2: UIBarButtonItem = { 
    let barButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(action2)) 
    return barButtonItem 
    } 

    override func viewDidLoad() { 
    super.viewDidLoad() 

    print(barButtonItem1.target, barButtonItem2.target) 
    } 
} 

Les résultats imprimés ont montré que barButtonItem1.target était nulle, et barButtonItem2.target était soi-même, qui semble fou! J'ai eu ce problème quand j'utilise l'écriture paresseuse var de barButtonItem1, et puis j'ai trouvé que l'action de barButtonItem1 ne peut jamais être appelée, et finalement le problème était barButtonItem1.target était nul.

Je ne sais pas pourquoi cela se produit, mais je suis sûr que c'est un bug. Est-ce que quelqu'un sait quelque chose à ce sujet? J'apprécierai vraiment si vous pouvez expliquer à ce sujet.

+1

Je ne pense pas que vous faites 'barButtonItem1' correctement. Tout d'abord 'lazy var' doit être déclaré avec un type de données. Deuxièmement, vous définissez simplement sa valeur comme une variable régulière. S'il vous plaît lire: https: //www.hackingwithswift.com/example-code/language/what-are-paresseux-variables – thedp

+0

La déclaration de barButtonItem1 devrait être correcte, selon [link] (https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language /Properties.html). – user5685969

+1

Selon [link] (https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html), la déclaration de barButtonItem1 doit être correcte. Cependant j'ai essayé ce que vous avez dit pour ajouter une déclaration de type de données pour barButtonItem1, et il se comporte bien maintenant. Je ne sais toujours pas ce qui cause ça. – user5685969

Répondre

3

Explication ci-dessous est ma conjecture. Et malheureusement, je n'ai pas assez de réputation pour faire un commentaire alors laissez-moi vous donner une réponse.

Ma conjecture: c'est un bug du compilateur.


D'abord, j'ai créé une petite extension de UIBarButtonItem. (Second paramètre est pas de Any? mais UIViewController?)

extension UIBarButtonItem { 
    convenience init(barButtonSystemItem systemItem: UIBarButtonSystemItem, targetViewController: UIViewController?, action: Selector?) { 
     // call the initializer provided by UIKit 
     self.init(barButtonSystemItem: systemItem, target: targetViewController, action: action) 
    } 
} 

Alors j'ai essayé d'initialiser la variable stockée paresseuse avec le code ci-dessous.

class ViewController: UIViewController { 

    lazy var barButtonItem1 = UIBarButtonItem(barButtonSystemItem: .cancel, targetViewController: self, action: #selector(action)) 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     print(barButtonItem1.target) 
    } 
    func action() { } 
} 

compilateur Puis erreur élevé et dire

Impossible de convertir la valeur de type '(NSObject) ->() -> ViewController' à type d'argument attendu 'UIViewController?

qui suggère que le compilateur n'a pas réussi à déterminer que self est de ViewController. (Le initialisateur par UIKit compilerions parce que le second paramètre est de Any? qui accepte la valeur de type (NSObject) ->() -> ViewController.)

Mais quand annotation de type donnent à la variable paresseux comme

code source
lazy var barButtonItem1: UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, targetViewController: self, action: #selector(action)) 

heureusement compilé et barButtonItem1.target a été défini sur self. Je crois que l'annotation de type a aidé à compiler. Ci-dessus est la raison pour laquelle je suppose que le problème que vous avez rencontré est causé par un bug du compilateur.


Voir aussi: Il y aurait des problèmes similaires à la question que vous face. Les deux sont conclus comme un bug de compilateur.

Swift lazy instantiating using self

Type inference when using lazy instantiation

+0

Merci! Donc, c'est vraiment un bug du compilateur, espérons que Apple le corrigera bientôt. Pour l'instant, ajoutons simplement l'annotation de type. – user5685969