[SWIFT 3] Conversion de couleur hexa

InsouInsou Membre
juillet 2017 modifié dans API UIKit #1

Bonjour tout le monde,


 


J'ai un petit soucis qui me parait simple mais pourtant je tourne en rond :/


 


En gros, je récupère via json, une couleur hexa (ex : #FF0000) que je stock comme ça :



let defaults = UserDefaults.standard
defaults.set(recupJSON["Data","Societe","CouleurHexApplication"].stringValue, forKey: "CouleurHex")

Plus loin dans mon code, j'ai une fonction pour récupérer la couleur :



func getColorBox() -> UInt {
let defaults = UserDefaults.standard
if let CouleurHex = defaults.value(forKey: "CouleurHex") {
if(String(describing: CouleurHex) != ""){
let newCouleurHex = Int((CouleurHex as! String).replacingOccurrences(of:"#", with: "0x"))!
print(newCouleurHex)
return UInt(newCouleurHex)
}
else{
return 0xF37612 // couleur par défaut
}
}
return 0xF37612 // couleur par défaut
}

et je dois utiliser la couleur récupérée comme ça :



SCLAlertView().showTitle(
"Congratulations", // Title of view
subTitle: "Operation successfully completed.", // String of view
duration: 2.0, // Duration to show before closing automatically, default: 0.0
completeText: "Done", // Optional button value, default: ""
style: .Success, // Styles - see below.
colorStyle: 0xA429FF // example de la couleur ici
)

Sauf que je me retrouve toujours avec une erreur de type "Cannot convert value of type UInt to expected argument type UIColor"


 


J'ai bien compris que j'essayais de mettre du UInt alors qu'il me demande du UIColor donc normal que ça fonctionne pas..


 


J'ai testé beaucoup de bout de code trouvé par ci, par là  pour convertir mes valeurs dans tout les sens.. mais ça foire toujours, j'ai l'impression qu'il y a un truc tout bête que je n'ai pas compris..


 


Quelqu'un y voit plus clair que moi ? ^^


 


Merci de votre aide :)


Mots clés:

Réponses

  • Joanna CarterJoanna Carter Membre, Modérateur
    juillet 2017 modifié #2

    extension UIColor
    {
    convenience init(hexValue: UInt)
    {
    let red = Float((hexValue & 0xFF0000) >> 16) / 255.0

    let green = Float((hexValue & 0xFF00) >> 8) / 255

    let blue = Float(hexValue & 0xFF) / 255

    self.init(colorLiteralRed: red, green: green, blue: blue, alpha: 1.0)
    }
    }

    en code :



    let color = UIColor(hexValue: 0xF37612)
  • J'ai ajouté ce bout de code (j'en avais testé un similaire ^^)..


     


    Par contre, j'ai une erreur dans la fonction getColorBox()



    func getColorBox() -> UInt {
    let defaults = UserDefaults.standard
    if let CouleurHex = defaults.value(forKey: "CouleurHex") {
    if(String(describing: CouleurHex) != ""){
    let newCouleurHex = Int((CouleurHex as! String).replacingOccurrences(of:"#", with: "0x"))! // L'ERREUR EST ICI
    print(newCouleurHex)
    return UInt(newCouleurHex)
    }
    else{
    return 0xF37612
    }
    }
    return 0xF37612
    }

    "fatal error: unexpectedly found nil while unwrapping an Optional value"


     


    J'ai l'impression que je pige pas bien le truc avec # et 0x aussi :s


  • DrakenDraken Membre
    juillet 2017 modifié #4

    func getColorBox() -> UInt {
    let defaults = UserDefaults.standard
    if let CouleurHex = defaults.value(forKey: "CouleurHex") {
    if(String(describing: CouleurHex) != ""){
    let newCouleurHex = Int((CouleurHex as! String).replacingOccurrences(of:"#", with: "0x"))!
    print(newCouleurHex)
    return UInt(newCouleurHex)
    }
    else{
    return 0xF37612 // couleur par défaut
    }
    }
    return 0xF37612 // couleur par défaut
    }

    Il est bien compliqué ton code. Deux return par défaut avec la même valeur ?? Et je ne voit pas l'intérêt de toutes ces conversions dans la lecture de la valeur. Tu devrais faire les conversions en lisant le JSON et stocker en mémoire une information correcte, un Uint dans le cas présent.


     


     


    De plus tu forces un casting avec l'opérateur as! au risque d'avoir une fatal error. Tueur de poney !


     


    La première chose a faire pour localiser le problème est d'afficher la valeur des paramètres de ta fonction. Le casting de CouleurHex échoue, mais que contient-elle vraiment ? En passant les conventions de nommage en Swift disent qu'on ne doit JAMAIS commencer un nom de variable par une majuscule. C'est réservé aux noms de classes, pour les pouvoir les identifier d'un simple regard sans réfléchir.


  • Joanna CarterJoanna Carter Membre, Modérateur
    juillet 2017 modifié #5

    Mais non !


     


    1. Pourquoi t'as ignoré mon dernier post ?


     



    "fatal error: unexpectedly found nil while unwrapping an Optional value"



     


    ... est toujours le résultat d'utiliser les ! !!!


     


    Tu as fait :



    let newCouleurHex = Int((CouleurHex as! String).replacingOccurrences(of:"#", with: "0x"))!

    Du coup, t'as dit que tu es absolument certain que CouleurHex est un String valid !!!


     


    C'est quoi comme type, la valeur récupérée de tes UserDefaults ?


     


    S'il est bien un Int ou UInt, pourquoi la transformer en String ?


  • InsouInsou Membre
    juillet 2017 modifié #6

    Bon je vais recommencer depuis le début, on y verra surement plus clair ^^


     



    Tu devrais faire les conversions en lisant le JSON et stocker en mémoire une information correcte, un Uint dans le cas présent.



     


    Dac'..


    Alors quand je reçois mon json, voici mon code pour stocker la valeur :


    Je reçois une couleur en hexa (ex : #FF0000) en string.



    defaults.set(recupJSON["Data","Societe","CouleurHexApplication"].uIntValue, forKey: "CouleurHex")
    print(" ")
    print(recupJSON["Data","Societe","CouleurHexApplication"].stringValue)
    print(recupJSON["Data","Societe","CouleurHexApplication"].uInt)
    print(" ")

    Sauf que rien que là , je pense que j'ai un soucis.. voici ce qu'affiche la console..


     




    #ED6600


    nil




     


    nil quand je le converti en uInt ? :/


    C'est surement pour ça que ça merdouille dans ma fonction..


    En même temps, ça me parait normal que ça foire quand j'essaie de converti cette valeur (#ED6600 / String) en UInt..


  • Joanna CarterJoanna Carter Membre, Modérateur
    juillet 2017 modifié #7

    Que fait :



    recupJSON[...] ???

    Tu peux nous montrer du code ?


  • InsouInsou Membre
    juillet 2017 modifié #8

    j'utilise SwiftyJSON pour traité le json que je reçois..



    let recupJsonSync = Alamofire.request(monUrl, method: .post, parameters: parametres).responseJSON()

    switch recupJsonSync.result {
    case .success:
    if let value = recupJsonSync.result.value {
    let recupJSON = JSON(value)

    ...
  • Joanna CarterJoanna Carter Membre, Modérateur
    juillet 2017 modifié #9

    Oui, mais le code :



    if let value = recupJsonSync.result.value {
    let recupJSON = JSON(value)

    te donne quoi comme type pour value ?


     


    ça devrait te donner un [String: Any] qui est un dictionnaire




  •  


    j'utilise SwiftyJSON pour traité le json que je reçois..




     


    Pour infos, Swift 4, disponible en Septembre/Octobre est capable de traiter directement le Json sans passer par une bibliothèque externe. On peut déjà  télécharger Xcode 9 bêta pour commencer à  préparer le changement. 

  • InsouInsou Membre
    juillet 2017 modifié #11

    let value: Any


    let recupJSON: JSON // swiftyJson

     


    Après via SwiftyJson, je peux caster les valeurs comme bon me semble..


    https://github.com/SwiftyJSON/SwiftyJSON#non-optional-getter


     


    D'où mon : 



    recupJSON["Data","Societe","CouleurHexApplication"].stringValue

    Pour moi, je stock la valeur hexa que je reçois (en string) dans ma clé "CouleurHex"


     


    Et quand j'en ai besoin, je comptais appeler ma fonction getColorBox() qui me renverrai ma couleur au bon format (donc pas en string) pour l'utiliser ici :



    let maCouleur = getColorBox()

    SCLAlertView().showTitle(
    "Congratulations", // Title of view
    subTitle: "Operation successfully completed.", // String of view
    duration: 2.0, // Duration to show before closing automatically, default: 0.0
    completeText: "Done", // Optional button value, default: ""
    style: .Success, // Styles - see below.
    colorStyle: maCouleur // ma couleur ici
    )

    Je voulais donc convertir mon string "#FF0000" pour avoir le bon format (UInt ou UIColor ?)


     



    Pour infos, Swift 4, disponible en Septembre/Octobre est capable de traiter directement le Json sans passer par une bibliothèque externe. On peut déjà  télécharger Xcode 9 bêta pour commencer à  préparer le changement. 



     


    Ouai j'ai vu ça mais je ne peux pas tout changer maintenant juste pour traité directement du json ^^


    Pour l'instant la bibliothèque externe ira très bien ^^


  • En fait je viens de me rendre compte qu'il me faut parfois du UInt et parfois du UIColor..


    Mais à  la base j'ai que ça : "#FF0000" en string..


     


    Du coup, c'est la conversion vers UInt et UIColor où j'ai du mal :s


  • Joanna CarterJoanna Carter Membre, Modérateur
    juillet 2017 modifié #13

    Tu devrais suivre nos conseils si tu veux réussir avec la programmation !!!


     


    1. Ne commences pas les noms des vars/lets avec les majuscules ; tu pourras lire et comprendre ton code plus vite (et nous aussi)


     


    2. Tu devrais créer les vars/lets intermédiaires pour mieux comprendre où se trouvent les erreurs. Ne fait pas les lignes de code complexe.


     


    Côté conversion de String en UIColor :



    extension UIColor
    {
    convenience init(hex: String)
    {
    let scanner = Scanner(string: hex)

    scanner.scanLocation = 0

    var rgbValue: UInt64 = 0

    scanner.scanHexInt64(&rgbValue)

    let red = Float((rgbValue & 0xff0000) >> 16) / 255.0

    let green = Float((rgbValue & 0xff00) >> 8) / 255.0

    let blue = Float(rgbValue & 0xff) / 255.0

    self.init(colorLiteralRed: red, green: green, blue: blue, alpha: 1)
    }
    }


    let rawColorString = "#F37612"

    let colorString = rawColorString.substring(from: rawColorString.index(after: rawColorString.startIndex))

    let color = UIColor(hex: colorString)

  • Joanna CarterJoanna Carter Membre, Modérateur

    Ou, tu peux utiliser une extension fait exprès pour les strings hex qui commencent avec un '#'



    extension UIColor
    {
    convenience init(jsonHex: String)
    {
    let scanner = Scanner(string: JsonHex)

    scanner.scanLocation = 1 // pour ignorer le #

    var rgbValue: UInt64 = 0

    scanner.scanHexInt64(&rgbValue)

    let red = Float((rgbValue & 0xff0000) >> 16) / 255.0

    let green = Float((rgbValue & 0xff00) >> 8) / 255.0

    let blue = Float(rgbValue & 0xff) / 255.0

    self.init(colorLiteralRed: red, green: green, blue: blue, alpha: 1)
    }
    }


    let colorString = "#F37612"

    let color = UIColor(jsonHex: colorString)

  •  


    1. Ne commences pas les noms des vars/lets avec les majuscules ; tu pourras lire et comprendre ton code plus vite (et nous aussi)



     


    Ouai, c'est une mauvaise habitude que j'dois corriger, j'vais le faire petit à  petit quand je repasserai dans mon code..


    Par contre, c'est pas ça qui fait que je vais "réussir en programmation"  ???


    J'comprends que ça respecte pas vraiment les conventions de nommage mais perso j'me fie pas à  une majuscule pour savoir si c'est une variable ou pas ^^


    Le code est assez clair pour savoir ce que c'est ^^


     



     


    2. Tu devrais créer les vars/lets intermédiaires pour mieux comprendre où se trouvent les erreurs. Ne fait pas les lignes de code complexe.



     


    Yes, c'est ce que j'essaie de faire le plus souvent possible..


     


    Pour le string vers UIColor, c'est good, ça marche nickel, merci :)


     


    Pour le string vers UInt, j'ai fais comme ça : 



    let colorString = "0xFF0000"
    print(colorString)
    if let hexValue = UInt(String(colorString.characters.suffix(6)), radix: 16) {
    print(hexValue)
    }

    et du coup, c'est bon aussi, j'ai bien les bonnes couleurs aux bons endroits.


     


    Merci à  vous 2 :)


  • Joanna CarterJoanna Carter Membre, Modérateur
    juillet 2017 modifié #16


    J'comprends que ça respecte pas vraiment les conventions de nommage mais perso j'me fie pas à  une majuscule pour savoir si c'est une variable ou pas ^^


    Le code est assez clair pour savoir ce que c'est ^^




     


    Mais les majuscules sont utilisés pour les noms des types. Tu dis que c'est facile de différencier entre les noms de types et les noms des var/let ?


     


    En plus de 25 ans d'activité comme consultante, je l'ai entendu quelques fois mais c'est toujours eux qui le fassent qui prennent plus de temps pour déboguer son code  ::)


     




    Pour le string vers UInt, j'ai fais comme ça : 



    let colorString = "0xFF0000"
    print(colorString)
    if let hexValue = UInt(String(colorString.characters.suffix(6)), radix: 16) {
    print(hexValue)
    }

    et du coup, c'est bon aussi, j'ai bien les bonnes couleurs aux bons endroits.




     


    Mais, pourquoi te veux le couleurs comme UInt ? De mon avis ça ne sert à  rien  ???


  • Bah dans tout les cas, si j'ai un doute sur une variable/classe, je peux voir ce que c'est exactement en cliquant dessus avec "alt" nan ? ^^


     



     


    En plus de 25 ans d'activité comme consultante, je l'ai entendu quelques fois mais c'est toujours eux qui le fassent qui prennent plus de temps pour déboguer son code ::)



     


    ahah, ça m'étonne pas..


    D'ailleurs j'dis pas que ça sert à  rien de respecter les conventions de nommage.. au contraire, c'est juste que j'suis sur un projet tout seul, il n'y a que moi qui travail sur le code donc bon.. si ma variable a une majuscule, c'est pas la fin du monde non plus ^^


    Après j't'avoue que si je travaillais en équipe sur un gros projet, je ferai surement plus attention à   ce genre de détails ^^


    Enfin bon, j'vais essayé d'être plus rigoureux pour mes prochaines variable :p


     



     


    Mais, pourquoi te veux le couleurs comme UInt ? De mon avis ça ne sert à  rien  ???



     


    A un moment, SCLAlert me demande une couleur en UInt


    Vu que je veux mettre la même couleur que je récupère, j'ai converti le string (0xF00000) en Uint et ça fonctionne très bien.


     


    En gros, je recupère une couleur en hexa (String) et j'ai besoin de cette couleur sous 2 formats (UiColor et UInt) pour 2 endroits différents.


  • Joanna CarterJoanna Carter Membre, Modérateur
    juillet 2017 modifié #18


    A un moment, SCLAlert me demande une couleur en UInt


    Vu que je veux mettre la même couleur que je récupère, j'ai converti le string (0xF00000) en Uint et ça fonctionne très bien.


     


    En gros, je recupère une couleur en hexa (String) et j'ai besoin de cette couleur sous 2 formats (UiColor et UInt) pour 2 endroits différents.




     


    Tu pourrais aussi ajouter encore une extension à  UIColor :



    extension UIColor
    {
    func rgbHex() -> UInt
    {
    var red: CGFloat = 0.0
    var green: CGFloat = 0.0
    var blue: CGFloat = 0.0
    var alpha: CGFloat = 0.0

    guard self.getRed(&red, green: &green, blue: &blue, alpha: &alpha) else
    {
    return 0
    }

    return UInt((lrintf(Float(red) * 0xFF) << 16) | (lrintf(Float(green) * 0xFF) << 8) | (lrintf(Float(blue) * 0xFF)))
    }
    }

    Mais je dois dire que je trouve le code de SCLAlert moche et mal écrit. Enfin, il transforme l'UInt en UIColor à  l'intérieur, pourquoi pas accepter un UIColor comme paramètre ?


  • Ouai j'aurai pu faire une extension en effet.. mais pour le coup, elle est plus compliqué à  comprendre que ma ligne de code ^^


    Mais niveau cohérence, c'est vrai que c'est mieux (mettre toute les fonctions de transformation au même endroit sous forme d'extension).


     



     


    Mais je dois dire que je trouve le code de SCLAlert moche et mal écrit. Enfin, il transforme l'UInt en UIColor à  l'intérieur, pourquoi pas accepter un UIColor comme paramètre ?



     


    Faudrait demander au développeur du projet :p


    J'ai aussi trouvé ça bizarre de faire comme ça.. on a du UIColor, autant s'en servir partout..


    Au début j'avais pas remarqué.. j'm'en suis rendu compte via mon post de 13h44 ^^


Connectez-vous ou Inscrivez-vous pour répondre.