[RESOLU][NOOB en SWIFT] Comparaison avec nil

DrakenDraken Membre
décembre 2014 modifié dans Objective-C, Swift, C, C++ #1

En commençant à  bricoler avec Swift, j'ai voulu comparer la valeur d'un objet avec nil, obtenant un résultat curieux.


 


J'ai créé une petite classe de test, dérivant de UIView, avec une propriété listeTextes.



var listeTextes:NSMutableArray?

L'idée est d'afficher les textes dans le drawRect. J'ai commencé par tester si listeTextes est différent de nil, ce que le compilateur n'apprécie pas.



override func drawRect(rect: CGRect) {

// CA COMPILE PAS !!
if (listeTextes!=nil) {
}

}

Le message d'erreur est Type '()' does not conform to protocol 'BooleanType'


Il pointe sur le '!='


 


Par contre, le test d'égalité '==' ne fait pas hurler le compilateur



// çA COMPILE
if (listeTextes==nil) {
}

L'inversion booléenne du test d'égalité se compile sans problème.



// CA COMPILE
if (!(listeTextes==nil)) {
}

Une idée pour éclairer ma lanterne de noob, sur la différence de comportement des opérateurs '==' et '!=' ? 


 


 


Le code complet (Xcode 6.1.1) :



class UnePetiteVue: UIView {

var listeTextes:NSMutableArray?

override init(frame: CGRect) {
super.init(frame: frame)

}

required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override func drawRect(rect: CGRect) {
// Drawing code

// çA COMPILE
if (listeTextes==nil) {

}

// çA NE COMPILE PAS !!
if (listeTextes!=nil) {

}

// çA COMPILE
if (!(listeTextes==nil)) {

}

}

}

Réponses

  • amadehamadeh Membre
    décembre 2014 modifié #2

    Salut Draken,


     


    Un Optional en swift commence avec une valeur nil jusqu'à  que une valeur lui ai été attribuée.


     


    Si tu veux faire le test que tu veux faire, il faut que tu fasses :



    if listeTextes {
    println('NOT NIL")
    }

    Je t'invite aussi à  regarder le pattern :



    if let myvariable = possibleValue {
    }
  • AliGatorAliGator Membre, Modérateur
    décembre 2014 modifié #3
    Rajoute un espace autour de ton opérateur "!=" et ça va compiler. D'ailleurs toutes les conventions de codage incitent à  toujours mettre des espaces autour des opérateur, pour la lisibilité entre autres, mais pas que, la preuve.


    En fait ce que tu as écrit dans ton code c'est pas "listeTextes != nil" mais "listeTextes! = nil" ce qui n'a rien à  voir ! Si je rajoute des parenthèses pour la lisibilité ça donne l'équivalent de : " if ( (listeTextes!) = nil )"


    Ce que tu as écrit demande de forcer à  unwrapper ton optional listeTextes (donc à  dire au compilateur "pour moi il n'est pas nil donc je te demande d'en extraire la variable pour le transformer en non-optional de force"). Ca te donne alors un NSMutableArray (non-optional puisque tu viens de forcer à  l'unwrapper) " ou alors ça crashera au runtime si en fait il est vraiment nil et que tu as forcé à  l'unwrapper quand même.


    Ensuite une fois l'unwrapping effectué ton code demande d'affecter à  ce résultat la valeur nil. Ce qui a la base n'a pas de sens (car tu cherches à  affecter une valeur au résultat d'un unwrapping, et non pas directement à  la variable, comme si tu écrivais un truc comme "a+b = 3")...et même si ça avait du sens, en Swift une affectation ne retourne rien, donc le résultat d'une expression "x = y" retourne Void.

    Or Void (ou "()") ne peut pas être évalué / converti en Boolean (ce n'est pas un BooleanConvertible) pour être évalué par le "if", d'où l'erreur qu'il te sort (il détecte cette erreur de "une affectation retourne "()" soit Void et Void n'est pas convertible en booléen pour le if" avant même de détecter l'erreur de "l'affectation demandée n'est pas possible")
  • DrakenDraken Membre
    décembre 2014 modifié #4


  •  


    Salut Draken,


     


    Un Optional en swift commence avec une valeur nil jusqu'à  que une valeur lui ai été attribuée.


     


    Si tu veux faire le test que tu veux faire, il faut que tu fasses :



    if listeTextes {
    println('NOT NIL")
    }



    ça ne passe pas à  la compilation. Le compilateur m'affiche le message d'erreur "Optionnel type '@lvalue NSMutableArray?' cannot be used a boolean; test for '!= nil' instead"


     


    Heureusement, comme le dit Ali, il suffit d'un espace pour régler le problème.

  • AliGatorAliGator Membre, Modérateur
    Oui ça passait au tout début dans les premières versions de Swift le test "if x" pour sous-entendre "if x != nil".

    Mais maintenant ça ne passe plus et il faut être explicite, soit avec un "if x != nil" soit avec un "if let rx = x" (qui fait un optional mapping en + de faire un test de nullité de la variable)


    Et c'est fait pour que ça doive être explicite, pour éviter les confusions surtout quand tu utilises des booléens optionals (Bool?) car là  on a vite fait de confondre "if x != nil" de "if x! == true".


    PS pour rappel en Swift les parenthèses autour de la condition du "if" ne sont pas obligatoires.
Connectez-vous ou Inscrivez-vous pour répondre.