La chaîne attribuée avec des polices personnalisées dans le storyboard ne se charge pas correctement


100

Nous utilisons des polices personnalisées dans notre projet. Cela fonctionne bien dans Xcode 5. Dans Xcode 6, cela fonctionne en texte brut, chaîne attribuée dans le code. Mais ces chaînes attribuées définies dans le storyboard reviennent toutes à Helvetica lorsqu'elles sont exécutées sur un simulateur ou un appareil, bien qu'elles aient l'air bien dans le storyboard.

Je ne sais pas s'il s'agit d'un bogue du SDK Xcode 6 ou iOS 8, ou si la façon d'utiliser les polices personnalisées est modifiée dans Xcode 6 / iOS 8?


Même problème ici. J'adorerais savoir ce qui se passe.
obeattie le

1
Pour l'instant, nous avons créé un UILabel personnalisé, nommé GLMarkdownLabel, et exporté certaines propriétés avec IBInspectable, puis défini des chaînes de démarque dans le storyboard et converti les chaînes de démarque en chaînes attribuées lors de la réveil de nib.
Allen Hsu

C'est maintenant une solution à long terme, j'espère qu'Apple corrigera ce bogue dans la prochaine version de Xcode.
Allen Hsu

Yikes, une telle cruauté. Merci de nous avoir fait savoir que ce n'est pas un problème isolé. Y a-t-il un radar?
obeattie le

1
Notre solution de contournement revenait finalement à utiliser IBCustomFonts pour nos étiquettes attribuées.
yonix

Réponses:


30

Le correctif pour moi était d'utiliser une IBDesignableclasse:

import UIKit

@IBDesignable class TIFAttributedLabel: UILabel {

    @IBInspectable var fontSize: CGFloat = 13.0

    @IBInspectable var fontFamily: String = "DIN Light"

    override func awakeFromNib() {
        var attrString = NSMutableAttributedString(attributedString: self.attributedText)
        attrString.addAttribute(NSFontAttributeName, value: UIFont(name: self.fontFamily, size: self.fontSize)!, range: NSMakeRange(0, attrString.length))
        self.attributedText = attrString
    }
}

En vous donnant ceci dans Interface Builder:

Police personnalisée Interface Builder avec chaîne attribuée

Vous pouvez configurer votre chaîne attribuée comme vous le faites normalement, mais vous devrez à nouveau définir votre taille de police et votre famille de polices dans les nouvelles propriétés disponibles.

Comme l'Interface Builder fonctionne avec la police personnalisée par défaut, il en résulte que ce que vous voyez est ce que vous obtenez , ce que je préfère lors de la création d'applications.

Remarque

La raison pour laquelle j'utilise ceci au lieu de la version simple est que je définis des propriétés sur l'étiquette attribuée comme l'espacement des lignes, qui ne sont pas disponibles lors de l'utilisation du style simple.


1
Votre solution ne prend en charge qu'une seule famille de polices et une seule taille pour une étiquette, alors pourquoi ne pas utiliser simplement du texte brut à la place?
Allen Hsu

De même, nous utilisons @IBInspectabletemporairement des attributs au lieu de la police et de la taille. Nous avons une markdownTextpropriété, car la plupart du temps, nous utilisons une chaîne attribuée pour le texte en gras ou souligné. Ensuite, analysez le texte de démarque en chaîne attribuée avec les informations de police et de taille définies pour le texte brut.
Allen Hsu

@AllenHsu, vous avez raison. Je n'ai pas mentionné cela, mais j'utilise l'espacement des lignes attribué pour mon étiquette. Offcourse, sinon vous utiliseriez simplement le style simple :)
Antoine

bon point, nous avons également exporté lineSpacing: p Je pense que j'accepterais votre réponse car c'est en fait un bogue dans Xcode, et il n'y a pas de meilleure solution pour le moment. Attendons la prochaine version de Xcode.
Allen Hsu

2
Cela ne fonctionnera pas si je veux mettre en gras une partie du texte
xtrinch

28

La réponse la plus simple qui a fonctionné est de faire glisser les polices dans FontBook. Si les polices sont dans votre projet mais pas dans FontBook de votre ordinateur, IB a parfois du mal à les trouver. Bizarre, mais a travaillé pour moi à plusieurs reprises.


17
Bien que cela laisse Xcode sélectionner la police personnalisée, cela ne fonctionne pas réellement. Au moment de l'exécution, la police ne sera pas utilisée comme prévu.
Daniel

Malheureusement, je n'ai pas pu trouver une solution de contournement. Le mieux que je puisse faire était d'enregistrer un bogue avec Apple.
Daniel

Oui, c'est le correctif. J'ai fait concevoir mon storyboard par un autre développeur, svn update ok, mais je n'ai jamais eu la police dans l'interface utilisateur. La police figurait dans les ressources mais n'apparaissait pas dans l'interface utilisateur du périphérique / simulateur. Puisqu'il utilise une chaîne attribuée, je dois l'avoir dans Font Book. Cela résout le problème.
karim le

Oui. cela m'aide à résoudre le même problème. Lorsque j'ajoute une police personnalisée dans le livre de polices, les choses fonctionnent comme du charme.
Sushant Jagtap

1
Bien que cette solution fonctionne dans certains cas, j'ai également rencontré le même problème que @Daniel dans le même projet avec la même famille de polices. XCode doit résoudre ce problème.
dey.shin

16

Vous pouvez ajouter des polices personnalisées au livre de polices.

Étape 1 : Cliquez sur gérer les polices. Il ouvre le livre de polices.

entrez la description de l'image ici

Étape 2 : Cliquez sur plus et ajoutez vos polices.

entrez la description de l'image ici

La prochaine fois que vous cliquerez sur la police avec le texte attribué, la police nouvellement ajoutée apparaîtra également dans la liste. Mais assurez-vous que votre police personnalisée a été ajoutée dans info.plist et regroupez les ressources.


Cela fonctionne dans le storyboard, mais après l'avoir exécuté, ne montre pas le formatage
Van

1
Formatage @Van? Pouvez-vous m'en dire plus? Quand ça ne marche pas?
mahbaleshwar hegde

Je dois définir le texte qui est un mélange de police rgualr et gras. J'ai utilisé la solution ci-dessus, cela fonctionnait donc dans le storyboard, mais lorsque je lance l'application, l'étiquette n'indique pas la police appliquée à la place, elle montre la police système
Van

Avez-vous ajouté vos polices personnalisées dans info.plist? Après cela, imprimez simplement toutes les familles de polices
mahbaleshwar hegde

2
Oui. Je peux définir la police personnalisée partout dans l'application en cas de texte brut, je dois définir pour le texte attribué
Van

5

Grâce à ce fil, je suis arrivé à cette solution:

private let fontMapping = [
    "HelveticaNeue-Medium": "ITCAvantGardePro-Md",
    "HelveticaNeue": "ITCAvantGardePro-Bk",
    "HelveticaNeue-Bold": "ITCAvantGardePro-Demi",
]

func switchFontFamily(string: NSAttributedString) -> NSAttributedString {
    var result = NSMutableAttributedString(attributedString: string)
    string.enumerateAttribute(NSFontAttributeName, inRange: NSRange(location: 0, length: string.length), options: nil) { (font, range, _) in
        if let font = font as? UIFont {
            result.removeAttribute(NSFontAttributeName, range: range)
            result.addAttribute(NSFontAttributeName, value: UIFont(name: fontMapping[font.fontName]!, size: font.pointSize)!, range: range)
        }
    }
    return result
}

1
Bonne idée. C'est vraiment incroyable que ce soit cassé chez Apple. Étonnant.
Fattie le

4

Ma solution est un peu une solution. La vraie solution est pour Apple de réparer Interface Builder.

Avec lui, vous pouvez marquer tout le texte en gras et en italique dans le générateur d'interface à l'aide d'une police système, puis au moment de l'exécution, rendre votre police personnalisée. Peut ne pas être optimal dans tous les cas.

 NSMutableAttributedString* ApplyCustomFont(NSAttributedString *attributedText,
                     UIFont* boldFont,
                     UIFont* italicFont,
                     UIFont* boldItalicFont,
                     UIFont* regularFont)
{

    NSMutableAttributedString *attrib = [[NSMutableAttributedString alloc] initWithAttributedString:attributedText];
    [attrib beginEditing];
    [attrib enumerateAttribute:NSFontAttributeName inRange:NSMakeRange(0, attrib.length) options:0
                    usingBlock:^(id value, NSRange range, BOOL *stop)
    {
        if (value)
        {
            UIFont *oldFont = (UIFont *)value;
            NSLog(@"%@",oldFont.fontName);

            [attrib removeAttribute:NSFontAttributeName range:range];

            if([oldFont.fontName rangeOfString:@"BoldItalic"].location != NSNotFound && boldItalicFont != nil)
                [attrib addAttribute:NSFontAttributeName value:boldItalicFont range:range];
            else if([oldFont.fontName rangeOfString:@"Italic"].location != NSNotFound && italicFont != nil)
                [attrib addAttribute:NSFontAttributeName value:italicFont range:range];
            else if([oldFont.fontName rangeOfString:@"Bold"].location != NSNotFound && boldFont != nil)
                [attrib addAttribute:NSFontAttributeName value:boldFont range:range];
            else if(regularFont != nil)
                [attrib addAttribute:NSFontAttributeName value:regularFont range:range];
        }
    }];
    [attrib endEditing];

    return attrib;
}

Inspiré par ce post


4

J'ai eu du mal avec ce bogue: UILabel s'affiche correctement dans IB avec une police personnalisée mais ne s'affiche pas correctement sur l'appareil ou le simulateur (la police est incluse dans le projet et est utilisée dans les UILabels simples).

Enfin trouvé Attributed String Creator sur (Mac) App Store. Génère du code à placer dans votre application à l'endroit approprié. Fantastique. Je ne suis pas le créateur, juste un utilisateur heureux.


3

J'ai rencontré le même problème: la police d'attribut définie pour TextView dans le storyboard ne fonctionnait pas au moment de l'exécution avec XCode 6.1 et iOS 8 SDK.

Voici comment j'ai résolu ce problème, pourrait être une solution de contournement pour vous:

  1. ouvrez l'inspecteur d'attributs de votre vue de texte, changez le texte en "Plain"

  2. cliquez sur la croix pour supprimer le "wC hR" (rouge ci-dessous)

    entrez la description de l'image ici

  3. changez le texte en "Attribué", puis vous pouvez définir la police et la taille de votre texte.

  4. courir pour vérifier si cela fonctionne

Il semble que par défaut, aucune wC hRpropriété n'est définie, ni UILabelni UITextView.
Allen Hsu

par xcode 6, avez-vous défini un autre type de hauteur-largeur, comme "Largeur régulière | Toute hauteur", "Largeur compacte | Hauteur régulière"? parce que j'ai un projet développé dans Xcode 5 et que sa vue de texte attribuée fonctionne même avec iOS 8 SDK, j'ai vérifié les paramètres et trouvé que la seule différence est que Xcode 6 permet aux utilisateurs de définir la police pour différentes tailles d'appareils si vous définissez le texte dans "Plaine". Cette nouvelle configuration peut être la raison pour laquelle la définition du texte dans "attribué" mais la police ne fonctionne pas.
Zhihao Yang

1
utilisez-vous des polices personnalisées? Je veux dire des polices auto-intégrées, pas des polices système.
Allen Hsu

Aha, je pensais que les polices "personnalisées" que vous avez mentionnées sont celles proposées par Xcode à condition qu'elle ait la police "System".
Zhihao Yang

Cela ne fonctionne pas pour moi. Cela fonctionne pour une chaîne normale mais pas pour une chaîne attribuée.
Pratik Somaiya


2

Essayez ceci, cela fonctionnera

Dans mon cas, lorsque j'essaie de définir "Silversky Technology" comme texte attribué pour l'étiquette du constructeur d'interface, il ne s'affiche pas lorsque je lance dans le simulateur, mais il s'affiche dans le constructeur d'interface. J'ai donc utilisé une astuce: j'ai créé une police Silversky avec 1 pixel plus grand que le texte Technology.

Le texte d'attribut a un problème avec la même taille de police, alors changez la taille d'un mot, cette chose fonctionne avec moi.

C'est peut-être un bogue xcode, mais cette astuce fonctionne pour moi.


1

Le même problème.

Résolu: cochez simplement sélectionnable dans TextView. Sans cela, j'ai une police système standard.


1

Double-cliquez et installez la police sur le système. Cela fonctionnera (Xcode 8.2)


1
Je souhaite que ce soit le cas. Cela ne fonctionne pas pour moi avec FontAwesome.
Peter DeWeese

1

La solution @Hamidptb fonctionne, assurez-vous d'obtenir le nom correct de la police (une fois que vous l'avez ajoutée au livre de polices)

  • Ouvrez l'application Font Book, accédez à votre police puis appuyez sur Commande + I. Le nom PostScript est le nom de la police que vous souhaitez utiliser ici:

    UILabel.appearance (). Font = UIFont (nom: " PostScriptName ", taille: 17)


0

J'essayais d'obtenir des cellules tableView avec du texte comportant plusieurs paragraphes. Les chaînes attribuées semblaient être un moyen d'obtenir un espace supplémentaire entre les paragraphes (quelque chose d'un peu plus agréable que de faire deux sauts de ligne dans la chaîne). Je suis tombé sur ceci et d'autres articles lorsque j'ai découvert que les paramètres IB ne s'appliquaient pas au moment de l'exécution lorsque vous vouliez mettre un texte différent dans la cellule.

La principale chose que j'ai trouvée a été d'ajouter une extension à String (en utilisant Swift) pour créer une chaîne attribuée avec certaines caractéristiques. L'exemple ici utilise la police Marker Felt, car elle se distingue facilement de Helvetica. L'exemple montre également un petit espacement supplémentaire entre les paragraphes pour les rendre plus distincts les uns des autres.

extension String {
func toMarkerFelt() -> NSAttributedString {
    var style = NSMutableParagraphStyle()
    style.paragraphSpacing = 5.0
    let markerFontAttributes : [NSObject : AnyObject]? = [
        NSFontAttributeName : UIFont(name: "Marker Felt", size: 14.0)!,
        NSParagraphStyleAttributeName: style,
        NSForegroundColorAttributeName : UIColor.blackColor()
    ]
    let s = NSAttributedString(string: self, attributes: markerFontAttributes)
    return s
    }
}

Ensuite, dans ma tableViewCell personnalisée, vous lui envoyez le texte que vous souhaitez et il le convertit en une chaîne attribuée sur le UILabel.

//  MarkerFeltCell.swift
class MarkerFeltCell: UITableViewCell {
@IBOutlet weak var myLabel: UILabel!
func configureCellWithString(inputString : String) {
    myLabel.attributedText = inputString.toMarkerFelt()
}}

Dans le contrôleur de vue avec tableView, vous devez enregistrer votre cellule dans viewDidLoad () - J'ai utilisé une pointe, donc quelque chose comme:

let cellName = "MarkerFeltCell"
tableView.registerNib(UINib(nibName: cellName, bundle: nil), forCellReuseIdentifier: cellName)

Pour que la cellule détermine sa hauteur, créez une cellule prototype qui est utilisée pour obtenir des informations sur la taille et qui n'est jamais ajoutée à tableView. Donc, dans les variables de votre contrôleur de vue:

var prototypeSummaryCell : MarkerFeltCell? = nil

Puis dans (probablement remplacer - en fonction de votre contrôleur de vue) heightForRowAtIndexPath:

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        // ...
    if xib == "MarkerFeltCell" {
            if prototypeCell == nil {
                prototypeCell = tableView.dequeueReusableCellWithIdentifier(xib) as? MarkerFeltCell
            }
            let width : CGFloat = tableView.bounds.width
            let height : CGFloat = prototypeCell!.bounds.height
            prototypeCell?.bounds = CGRect(x: 0, y: 0, width: width, height: height)
            configureCell(prototypeCell!, atIndexPath: indexPath)
            prototypeSummaryCell?.layoutIfNeeded()
            let size = prototypeSummaryCell!.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
            let nextHeight : CGFloat = ceil(size.height + 1.0)
            return nextHeight
    } else {  // ...

Dans le code ci-dessus, le prototypeCell sera rempli la première fois qu'il sera nécessaire. Le prototypeCell est ensuite utilisé pour déterminer la hauteur de la cellule après le processus de dimensionnement automatique. Vous devrez arrondir la hauteur avec la fonction ceil (). J'ai également ajouté un facteur de fudge supplémentaire.

Le bit de code final est la façon dont vous configurez le texte de la cellule. Pour cet exemple, simplement:

func configureCell(cell :UITableViewCell, atIndexPath indexPath: NSIndexPath) {
    if let realCell = cell as? MarkerFeltCell  {
        realCell.configureCellWithString("Multi-line string.\nLine 2.\nLine 3.")    // Use \n to separate lines
    }
}

Aussi, voici une photo de la plume. Épinglé l'étiquette sur les bords de la cellule (avec une marge souhaitée), mais a utilisé une contrainte «Supérieur ou égal», avec une priorité inférieure à «Obligatoire» pour la contrainte inférieure.

Contraintes de cellule

Définissez la police de l'étiquette sur Attribuée. La police IB réelle n'avait pas d'importance.

LabelFont

Le résultat dans ce cas:

CellResults


0

En cas de chaîne attribuée, vous pouvez ajouter une police personnalisée dans la liste des polices comme - Cliquez sur l'icône de police pour afficher la boîte de dialogue suivante. Dans la boîte de dialogue suivante, vous pouvez ajouter votre propre catégorie ou une existante pour la police personnalisée. boîte de dialogue de police attribuée

Après avoir cliqué sur Gérer les polices, il ouvre la boîte de dialogue suivante, sélectionnez la catégorie que vous avez créée ou existante. Cliquez sur + signe pour ajouter une police dans la catégorie. Boîte de dialogue Gérer la police


0

c'est avoir une solution simple et rapide et cela fonctionne dans mon cas. cette solution consiste à ajouter une ligne de code dans la fonction didFinishLaunchingWithOptions du fichier AppDelegate.swift:

pour textViews :

UITextView.appearance().font = UIFont(name: "IranSans", size: 17)

pour les étiquettes :

UILabel.appearance().font = UIFont(name: "IranSans", size: 17)

et pour le reste de UiView comme celui-ci deux ☝️


0

Pour toute personne appliquant des polices personnalisées à une chaîne attribuée dans le code: essayez de la définir viewDidLayoutSubviews. Mon erreur a été de le faire viewDidLoad, cela ne sera pas appliqué là-bas.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.