La stringa attribuita con caratteri personalizzati nello storyboard non viene caricata correttamente


100

Stiamo utilizzando caratteri personalizzati nel nostro progetto. Funziona bene in Xcode 5. In Xcode 6, funziona in testo normale, stringa attribuita nel codice. Ma quelle stringhe attribuite impostate nello storyboard tornano tutte a Helvetica quando vengono eseguite sul simulatore o sul dispositivo, anche se sembrano a posto nello storyboard.

Non sono sicuro che si tratti di un bug di Xcode 6 o iOS 8 SDK, o il modo di utilizzare i caratteri personalizzati è cambiato in Xcode 6 / iOS 8?


Stesso problema qui. Mi piacerebbe sapere cosa succede.
ottenere il

1
Per ora, abbiamo creato un UILabel personalizzato, denominato GLMarkdownLabel, ed esportato alcune proprietà con IBInspectable, quindi impostato le stringhe di markdown nello storyboard e traducendo le stringhe di markdown in stringhe attribuite quando si risveglia dal pennino.
Allen Hsu,

Ora è una soluzione a lungo termine, spero che Apple risolva questo bug nella prossima versione di Xcode.
Allen Hsu,

Yikes, tale cruft. Grazie per averci informato che non si tratta di un problema isolato. C'è un radar?
ottenere il

1
La nostra soluzione alternativa alla fine è stata tornare a utilizzare IBCustomFonts per le nostre etichette attribuite.
yonix

Risposte:


30

La soluzione per me era usare una 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
    }
}

Dandoti questo in Interface Builder:

Carattere personalizzato di Interface Builder con stringa attribuita

Puoi impostare la tua stringa attribuita come fai normalmente, ma dovrai impostare nuovamente la dimensione del carattere e la famiglia di caratteri nelle nuove proprietà disponibili.

Poiché Interface Builder lavora con il carattere personalizzato per impostazione predefinita, ciò si traduce in ciò che vedi è ciò che ottieni , che preferisco quando creo app.

Nota

Il motivo per cui lo uso al posto della versione semplice è che sto impostando proprietà sull'etichetta attribuita come lo spaziatura di riga, che non sono disponibili quando si utilizza lo stile semplice.


1
La tua soluzione supporta solo una famiglia di caratteri e una dimensione per un'etichetta, quindi perché non utilizzare solo testo normale?
Allen Hsu

Allo stesso modo, stiamo usando gli @IBInspectableattributi temporaneamente, invece di font e dimensioni. Abbiamo una markdownTextproprietà, perché la maggior parte delle volte utilizziamo una stringa attribuita per il testo in grassetto o sottolineato. Quindi analizza il testo del markdown sulla stringa attribuita con le informazioni sul carattere e sulla dimensione impostate per il testo normale.
Allen Hsu

@AllenHsu, hai ragione. Non l'ho menzionato, ma sto usando la spaziatura di riga attribuita per la mia etichetta. Ovviamente, altrimenti useresti semplicemente lo stile semplice :)
Antoine

buon punto, abbiamo esportato anche lineSpacing: p Penso che accetterei la tua risposta poiché in realtà è un bug in Xcode, e per ora non c'è soluzione migliore. Aspettiamo la prossima versione di Xcode.
Allen Hsu

2
Questo non funzionerà se voglio mettere in grassetto una parte del testo
xtrinch

28

La risposta più semplice che ha funzionato è trascinare i caratteri in FontBook. Se i caratteri sono nel tuo progetto ma non nel FontBook del tuo computer, IB a volte ha problemi a trovarli. Strano, ma ha funzionato per me in diverse occasioni.


17
Sebbene ciò consentirà a Xcode di selezionare il carattere personalizzato, in realtà non funziona. In fase di esecuzione il carattere non verrà utilizzato come ci si aspetterebbe.
Daniel

Sfortunatamente non sono riuscito a trovare una soluzione alternativa. Il meglio che potevo fare era registrare un bug con Apple.
Daniel

Sì, questa è la soluzione. Ho fatto progettare il mio storyboard da un altro sviluppatore, aggiornamento svn ok, ma non ho mai ricevuto il carattere nell'interfaccia utente. Il carattere era nelle risorse ma non mostrato nell'interfaccia utente del dispositivo / simulatore. Dato che usa una stringa attribuita, devo averla in Libro Font. Questo risolve il problema.
karim

Sì. questo mi aiuta a risolvere lo stesso problema. Quando aggiungo un font personalizzato nel libro dei font, le cose funzionano come un fascino.
Sushant Jagtap

1
Sebbene questa soluzione funzioni in alcuni casi, ho anche affrontato lo stesso problema di @Daniel nello stesso progetto con la stessa famiglia di caratteri. XCode deve risolvere questo problema.
dey.shin

16

Puoi aggiungere caratteri personalizzati al libro dei caratteri.

Passaggio 1 : fare clic su Gestisci caratteri. Apre il libro dei font.

inserisci qui la descrizione dell'immagine

Passaggio 2 : fare clic su più e aggiungere i caratteri.

inserisci qui la descrizione dell'immagine

La prossima volta che fai clic sul carattere con il testo attribuito, anche il carattere appena aggiunto verrà visualizzato nell'elenco. Ma assicurati che il tuo font personalizzato sia aggiunto in info.plist e bundle resources.


Funziona nello storyboard ma dopo averlo eseguito non mostra la formattazione
Van

1
@Van formattazione? Puoi dirmi di più per favore? Quando non funziona?
mahbaleshwar hegde

Devo impostare il testo che è un mix match di rgualr e grassetto. Ho usato la soluzione sopra, quindi ha funzionato nello storyboard ma quando eseguo l'app l'etichetta non mostra il carattere applicato invece mostra il carattere di sistema
Van

Hai aggiunto i tuoi caratteri personalizzati in info.plist? Dopodiché stampa tutte le famiglie di caratteri
mahbaleshwar hegde

2
sì. Sono in grado di impostare il carattere personalizzato su tutta l'app in caso di testo normale, devo impostare per il testo attribuito
Van

5

Grazie a questo thread, sono arrivato a questa soluzione:

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
Bella idea. È davvero incredibile che questo sia rotto in Apple. Stupefacente.
Fattie

4

La mia soluzione è un po 'una soluzione. La vera soluzione è che Apple risolva Interface Builder.

Con esso puoi contrassegnare tutto il testo in grassetto e corsivo nel generatore di interfacce utilizzando un carattere di sistema, quindi in fase di esecuzione rendere il tuo carattere personalizzato. Potrebbe non essere ottimale in tutti i casi.

 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;
}

Ispirato da questo post


4

Ho lottato con questo bug: UILabel viene visualizzato correttamente in IB con font personalizzato ma non viene visualizzato correttamente sul dispositivo o sul simulatore (il font è incluso nel progetto e viene utilizzato in UILabels semplici).

Finalmente ho trovato Attributed String Creator su (Mac) App Store. Genera codice da inserire nella tua app nella posizione appropriata. Fantastico. Non sono il creatore, solo un utente felice.


3

Ho incontrato lo stesso problema: il carattere dell'attributo impostato per TextView nello storyboard non funzionava in fase di esecuzione con XCode 6.1 e iOS 8 SDK.

Ecco come ho risolto questo problema, potrebbe essere una soluzione alternativa per te:

  1. apri l'ispettore degli attributi della tua visualizzazione di testo, cambia il testo in "Semplice"

  2. clicca sulla croce per cancellare il "wC hR" (rosso sotto)

    inserisci qui la descrizione dell'immagine

  3. cambia il testo in "Attribuito", quindi puoi impostare il carattere e la dimensione del testo.

  4. corri a controllare se funziona

Sembra che per impostazione predefinita non ci siano wC hRproprietà impostate, né UILabelUITextView.
Allen Hsu

di xcode 6, hai impostato un altro tipo di altezza-larghezza, come "Larghezza normale | Altezza qualsiasi", "Larghezza compatta | Altezza normale"? poiché ho un progetto sviluppato in Xcode 5 e la sua visualizzazione del testo attribuita funziona anche con iOS 8 SDK, ho controllato le impostazioni e ho scoperto che l'unica differenza è che Xcode 6 consente agli utenti di impostare il carattere per diverse dimensioni di dispositivi se si imposta il testo in "Semplice". Questa nuova configurazione potrebbe essere il motivo per cui impostare il testo in "attribuito" ma il carattere non funziona.
Zhihao Yang

1
stai usando caratteri personalizzati? Intendo quelli autoincorporati, non i caratteri di sistema.
Allen Hsu

Aha, pensavo che i caratteri "personalizzati" che hai menzionato fossero quelli offerti da Xcode a condizione che abbia il carattere "Sistema".
Zhihao Yang

Per me non funziona. Funziona per una stringa normale ma non per una stringa attribuita.
Pratik Somaiya


2

Prova questo funzionerà

Nel mio caso, quando provo a impostare "Silversky Technology" come testo attribuito per l'etichetta dal generatore di interfacce, non viene visualizzato quando corro nel simulatore ma viene visualizzato nel generatore di interfacce. Quindi ho usato un trucco per rendere il font Silversky con 1 pixel più grande del testo Technology.

Il testo degli attributi ha problemi con la stessa dimensione del carattere, quindi cambia la dimensione di 1 parola questa cosa funziona con me.

Potrebbe essere questo bug di xcode, ma questo trucco funziona per me.


1

Lo stesso problema.

Risolto: basta selezionare Selezionabile in TextView. Senza questo ho il carattere di sistema standard.



1

La soluzione @Hamidptb funziona, assicurati di ottenere il nome corretto del carattere (dopo averlo aggiunto a Libro Font)

  • Apri l'applicazione Libro Font, vai al tuo font e premi Comando + I. Il nome PostScript è il nome del carattere che desideri utilizzare qui:

    UILabel.appearance (). Font = UIFont (nome: " PostScriptName ", dimensione: 17)


0

Stavo cercando di ottenere celle tableView con testo con più paragrafi. Le stringhe attribuite sembravano essere un modo per ottenere spazio extra tra i paragrafi (qualcosa di un po 'più bello rispetto a due avanzamenti di riga nella stringa). Mi sono imbattuto in questo e in altri post quando ho scoperto che le impostazioni IB non si applicavano in fase di esecuzione quando si desiderava inserire un testo diverso nella cella.

La cosa principale che mi è venuta in mente è stata l'aggiunta di un'estensione a String (utilizzando Swift) per creare una stringa attribuita con determinate caratteristiche. L'esempio qui utilizza il carattere Marker Felt, poiché è facilmente distinguibile da Helvetica. L'esempio mostra anche un po 'più di spaziatura tra i paragrafi per renderli più distinti l'uno dall'altro.

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
    }
}

Quindi, nel mio tableViewCell personalizzato, gli invii il testo che desideri e lo converte in una stringa attribuita su UILabel.

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

Nel controller di visualizzazione con tableView, dovresti registrare la tua cella in viewDidLoad () - Ho usato un pennino, quindi qualcosa del tipo:

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

Per far capire alla cella quanto dovrebbe essere alta, crea un prototipo di cella che viene utilizzato per ottenere informazioni sulla dimensione e non viene mai aggiunto in tableView. Quindi, nelle variabili del controller di visualizzazione:

var prototypeSummaryCell : MarkerFeltCell? = nil

Quindi in (probabilmente sovrascrivere - a seconda del controller della vista) 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 {  // ...

Nel codice precedente, prototypeCell verrà compilato la prima volta che è necessario. Il prototypeCell viene quindi utilizzato per calcolare l'altezza della cella dopo aver attraversato il processo di dimensionamento automatico. Dovrai arrotondare l'altezza con la funzione ceil (). Ho anche aggiunto qualche fattore di confusione extra.

Il bit di codice finale è il modo in cui configuri il testo per la cella. Per questo esempio, semplicemente:

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
    }
}

Inoltre, ecco uno scatto del pennino. L'etichetta è stata fissata ai bordi della cella (con il margine desiderato), ma è stato utilizzato un vincolo "Maggiore di o uguale", con una priorità inferiore a "Obbligatorio" per il vincolo inferiore.

Vincoli di cella

Imposta il carattere dell'etichetta su Attribuito. Il font IB effettivo non aveva importanza.

LabelFont

Il risultato in questo caso:

CellResults


0

In caso di stringa attribuita è possibile aggiungere un carattere personalizzato nell'elenco dei caratteri come - Fare clic sull'icona del carattere per visualizzare la seguente finestra di dialogo. Nella finestra di dialogo seguente è possibile aggiungere la propria categoria o una esistente per il carattere personalizzato. finestra di dialogo del carattere attribuito

Dopo aver fatto clic su Gestisci caratteri, si apre la seguente finestra di dialogo per selezionare la categoria in quella creata o esistente. Fare clic sul segno + per aggiungere il carattere nella categoria. Gestisci la finestra di dialogo dei caratteri


0

è una soluzione semplice e veloce e nel mio caso funziona. quella soluzione è aggiungere una riga di codice in didFinishLaunchingWithOptions func nel file AppDelegate.swift:

per textViews :

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

per etichette :

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

e per il resto di UiView come questo due ☝️


0

Per chiunque applichi caratteri personalizzati alla stringa attribuita nel codice: prova a impostarlo in viewDidLayoutSubviews. Il mio errore è stato farlo viewDidLoad, non verrà applicato lì.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.