Swift + NSAttributedString

Bon, je vous préviens, mes connaissances en Swift sont très limitées.

Pourquoi ai-je une erreur avec ce code:


let font = NSFont(name: "Helvetica", size: 32)
let attributes = [NSFontAttributeName: font]
let attributedString = NSAttributedString(string: "Toto", attributes:attributes)
L'erreur se trouve sur la dernière ligne: "Extra argument 'string' in call".

Merci de vos éclaircissements.

Réponses

  • AlakAlak Membre
    décembre 2014 modifié #2

    Je pense que c'est un bug de NSAttributedString


  • Joanna CarterJoanna Carter Membre, Modérateur
    Essayes ce :

    let attributedString = NSAttributedString("Toto", attributes:attributes)
  • CéroceCéroce Membre, Modérateur
    décembre 2014 modifié #4
    Non, toujours la même erreur.
    En plus, le premier argument a bien un nom d'après la doc.

  • let font = NSFont(name: "Helvetica", size: 32)!
    let attributes = [NSFontAttributeName: font]
    let attributedString = NSAttributedString(string: "Toto", attributes:attributes)

    voila


  • CéroceCéroce Membre, Modérateur
    Ah merci, ça fonctionne!
    Par contre, ça me semble totalement incompréhensible. Le message d'erreur est complètement faux et mal placé.

    Donc, effectivement, il y a une logique: il est possible que 'font' soit nil, mais le problème se situe au niveau du dictionnaire, plutôt, non ?
  • Exactement, le dictionnaire attendu est sensé être de type [NSObject: AnyObject]?


     


    personnellement je code comme ca :



    let font: NSFont = NSFont(name: "Helvetica", size: 32)!
    let attributes: [NSObject: AnyObject] = [NSFontAttributeName: font]
    let attributedString: NSAttributedString = NSAttributedString(string: "Toto", attributes:attributes)

    Sinon, effectivement le message d'erreur est lui même une erreur :s


  • CéroceCéroce Membre, Modérateur
    Cette version fonctionne et me semble plus correcte:


    if let font = NSFont(name: "Helvetica", size: 32) {
    let attributes = [NSFontAttributeName: font]
    let attributedString = NSAttributedString(string: "Toto", attributes:attributes)
    }
  • Joanna CarterJoanna Carter Membre, Modérateur
    Ouahuh ! Subtile.
  • muqaddarmuqaddar Administrateur

    Certains mettent le ! dans la ligne du dico plutôt:



     let font = UIFont(name: "Helvetica", size: 32)
     let attributes = [NSFontAttributeName: font!]
     let attributedString = NSAttributedString(string: "Toto", attributes:attributes)

    Qu'est-ce qui est mieux ?


  • CéroceCéroce Membre, Modérateur
    décembre 2014 modifié #11
    Dans l'exemple que tu donnes, une font nil pourrait être associée à  NSFontAttributeName.
    Dans ce cas précis, au pire, aucune fonte ne sera trouvée et NSAttributedString utilisera la fonte par défaut (Helvetica).
  • AliGatorAliGator Membre, Modérateur
    J'ai déjà  eu plusieurs fois ce genre d'erreur qui met sur une fausse piste avec Swift. C'est le meilleur moyen de perdre 1h à  chercher l'erreur alors que le problème ne se situe pas du tout là  où il dit qu'il est.

    C'est d'ailleurs une des raisons pour lesquelles je pense que le compilateur de Swift n'est pas encore prêt pour la production. Si on perd des heures à  cause d'un bug du compilateur, ça le fait pas dans un cadre de production !


    Le problème quand tu as cette erreur est souvent en fait qu'un des types qu'il attend dans la méthode n'est pas bon, car il n'arrive pas à  le caster comme il faut. J'ai déjà  eu ce cas avec un truc encore plus tordu: J'utilisais une API Objective-C en Swift (construction d'un UIBezierPath), et cette API attendait un CGFloat. Manque de pot, je passais en paramètre à  cette méthode non pas un CGFloat, mais une variable initialisée plus haut à  "1.0", ce qui était de type... Float, et pas CGFloat... résultat, j'ai eu cette erreur et ai essayé comme toi d'ajouter ou supprimer des paramètres, jusqu'à  finir par trouver que ce n'était pas les labels des paramètres qui n'étaient pas bons, mais le type Float qu'il n'arrivait pas à  convertir en CGFloat implicitement. 3/4 d'heure de perdus.
  • CéroceCéroce Membre, Modérateur
    Au départ, je voulais utiliser un Playground pour expérimenter avec Core Text, histoire de gagner du temps...
  • AliGatorAliGator Membre, Modérateur
    décembre 2014 modifié #14
    Si tu fais du Swift, et donc un truc un peu moderne, pourquoi utiliser CoreText ?
    Alors que depuis iOS6 on a TextKit, qui est quand même une API bien plus sympa, qui unifie les moteurs de rendu de texte UIKit et CoreFoundation en un seul et avec une API Objective-C (contre l'API C bien prise de tête et bas niveau de CoreText, j'en sais quelquechose...)
  • AliGatorAliGator Membre, Modérateur
    Et sinon, si tu veux te simplifier la vie avec les NSAttributedString, je te conseille mon pod OHAttributedStringAdditions.

    Sur le principe il ne fait rien de magique, c'est juste un wrapper, mais ça va te faciliter pas mal la vie : plutôt que de passer par leurs NSDictionary dont il faut se rappeler le nom des clés et surtout les types correspondants attendus à  chaque fois " et qui commencent à  être encore + prise de tête quand tu veux commencer à  mixer des styles qui s'overlappent, comme du gras sur les mots 3 à  10 et du italique sur les mots 7 à  12... "
    Tu fais juste des "[attrStr setFont:... range:...]" ou "[attrStr setTextBold:YES range:...]" et il se débrouille tout seul pour encapsuler les attributs, trouver les bonnes variantes "bold" de la police "non-bold" utilisée, etc...

    (Je l'ai pas encore testé avec Swift, mais y'a pas de raison que ça marche pas).

    Ca devrait pas mal te simplifier ton écriture de code... et sans doute t'éviter quelques mésaventures.


  • Bon, je vous préviens, mes connaissances en Swift sont très limitées.


    Pourquoi ai-je une erreur avec ce code:

     



    let font = NSFont(name: "Helvetica", size: 32)
    let attributes = [NSFontAttributeName: font]
    let attributedString = NSAttributedString(string: "Toto", attributes:attributes)

    L'erreur se trouve sur la dernière ligne: "Extra argument 'string' in call".


    Merci de vos éclaircissements.

     




     


    Pour éviter ces erreurs, une des préventions à  prendre est de toujours donner le type quand on le connait. C'est écrit dans la documentation.


    Donc pour reprendre l'exemple de Céroce passer de :



    let font = NSFont(name: "Helvetica", size: 32)

    à 



    let font: NSFont = NSFont(name: "Helvetica", size: 32)

    aurait du conduire Xcode à  indiquer de rajouter le "!" à  la fin de la première ligne et éviter de perdre des heures à  chercher.

  • Joanna CarterJoanna Carter Membre, Modérateur
    Si l'on ne veut que Helvetica, pourquoi pas utiliser NSFont.systemFontOfSize(...) etc afin que l'on evite les erreurs d'orthographe ?
  • muqaddarmuqaddar Administrateur


    Si l'on ne veut que Helvetica, pourquoi pas utiliser NSFont.systemFontOfSize(...) etc afin que l'on evite les erreurs d'orthographe ?




     


    Bah il faisait juste un test là ...

  • Joanna CarterJoanna Carter Membre, Modérateur

    Bah il faisait juste un test là ...




    Peut-être, mais le compilateur devrait être plus fiable ;)
  • CéroceCéroce Membre, Modérateur

    Si tu fais du Swift, et donc un truc un peu moderne, pourquoi utiliser CoreText ?
    Alors que depuis iOS6 on a TextKit, qui est quand même une API bien plus sympa, qui unifie les moteurs de rendu de texte UIKit et CoreFoundation en un seul et avec une API Objective-C (contre l'API C bien prise de tête et bas niveau de CoreText, j'en sais quelquechose...)

    Ben, déjà , c'est pas sur iOS.
    Ensuite je n'utilise pas Swift, j'utilise Core Text, et je me disais qu'un Playground pouvait être pratique pour tester.
  • AliGatorAliGator Membre, Modérateur
    décembre 2014 modifié #21
    Il y a un post récent sur le forum (je sais plus où) qui parlait d'un projet qui permettait de faire l'équivalent de Playground mais pour Objective-C. J'ai pas testé, mais ça pourrait être une piste si tu veux pas avoir Swift dans les pattes.


    [EDIT] Le post en question
  • CéroceCéroce Membre, Modérateur
    J'avais regardé mais le code d'injection ne fonctionne que sur iOS.
Connectez-vous ou Inscrivez-vous pour répondre.