Ciąg przypisany z niestandardowymi czcionkami w scenorysie nie ładuje się poprawnie

100

W naszym projekcie używamy niestandardowych czcionek. Działa dobrze w Xcode 5. W Xcode 6 działa jako zwykły tekst, z przypisanym ciągiem w kodzie. Ale te przypisane ciągi ustawione w scenorysie powracają do Helvetica podczas pracy na symulatorze lub urządzeniu, chociaż wyglądają dobrze w scenorysie.

Nie jestem pewien, czy jest to błąd w Xcode 6 lub iOS 8 SDK, czy też sposób korzystania z niestandardowych czcionek został zmieniony w Xcode 6 / iOS 8?

Allen Hsu
źródło
Mam ten sam problem. Chciałbym wiedzieć, co się dzieje.
obeattie
1
Na razie utworzyliśmy niestandardowy UILabel o nazwie GLMarkdownLabel i wyeksportowaliśmy niektóre właściwości za pomocą IBInspectable, a następnie ustawiliśmy ciągi znaczników w scenorysie i przetłumaczono ciągi znaczników z powrotem na przypisane ciągi po przebudzeniu ze stalówki.
Allen Hsu
Jest to teraz długoterminowe rozwiązanie, mam nadzieję, że Apple naprawi ten błąd w następnej wersji Xcode.
Allen Hsu
Ups, takie okropne. Dziękujemy za poinformowanie nas, że nie jest to jednak odosobniony problem. Czy jest radar?
obeattie
1
Ostatecznie naszym obejściem było używanie IBCustomFonts dla naszych przypisanych etykiet.
yonix

Odpowiedzi:

30

Rozwiązaniem dla mnie było użycie IBDesignableklasy:

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

Daje ci to w Interface Builder:

Niestandardowa czcionka programu Interface Builder z przypisanym ciągiem

Możesz skonfigurować przypisany ciąg tak jak zwykle, ale będziesz musiał ponownie ustawić rozmiar czcionki i rodzinę czcionek w nowych dostępnych właściwościach.

Ponieważ Interface Builder domyślnie pracuje z czcionką niestandardową, otrzymujesz to, co widzisz , co wolę podczas tworzenia aplikacji.

Uwaga

Powodem, dla którego używam tego zamiast zwykłej wersji, jest to, że ustawiam właściwości na przypisanej etykiecie, takie jak odstępy między wierszami, które nie są dostępne, gdy używam stylu prostego.

Antoine
źródło
1
Twoje rozwiązanie obsługuje tylko jedną rodzinę czcionek i rozmiar na etykiecie, więc dlaczego nie użyć zamiast tego zwykłego tekstu?
Allen Hsu,
Podobnie @IBInspectabletymczasowo używamy atrybutów zamiast czcionki i rozmiaru. Mamy markdownTextwłaściwość, ponieważ przez większość czasu używamy przypisanego ciągu dla tekstu pogrubionego lub podkreślonego. Następnie przeanalizuj tekst przeceny na przypisany ciąg z informacją o czcionce i rozmiarze ustawioną na zwykły tekst.
Allen Hsu,
@AllenHsu, masz rację. Nie wspominałem o tym, ale używam przypisanego odstępu między wierszami dla mojej wytwórni. Poza tym, w przeciwnym razie użyłbyś prostego stylu :)
Antoine
dobra uwaga, wyeksportowaliśmy również lineSpacing: p Myślę, że zaakceptowałbym twoją odpowiedź, ponieważ jest to w rzeczywistości błąd w Xcode i na razie nie ma lepszego rozwiązania. Poczekajmy na następną wersję Xcode.
Allen Hsu,
2
To nie zadziała, jeśli chcę pogrubić część tekstu
xtrinch
28

Najprostszą odpowiedzią, która zadziałała, jest przeciągnięcie czcionek do FontBook. Jeśli czcionki są w Twoim projekcie, ale nie znajdują się w FontBooku Twojego komputera, IB czasami ma problemy ze znalezieniem ich. Dziwne, ale działało dla mnie kilka razy.

Alan Scarpa
źródło
17
Pozwoli to Xcode na wybranie niestandardowej czcionki, ale w rzeczywistości nie działa. W czasie wykonywania czcionka nie będzie używana zgodnie z oczekiwaniami.
Daniel,
Niestety nie udało mi się znaleźć obejścia. Najlepsze, co mogłem zrobić, to zarejestrować błąd w Apple.
Daniel
Tak, to jest poprawka. Mój scenorys został zaprojektowany przez innego programistę, aktualizacja svn ok, ale nigdy nie otrzymałem czcionki w interfejsie użytkownika. Czcionka znajdowała się w zasobach, ale nie jest wyświetlana w interfejsie użytkownika urządzenia / symulatora. Ponieważ używa przypisanego ciągu, muszę go mieć w Albumie Czcionek. To rozwiązuje problem.
karim,
Tak. to pomaga mi rozwiązać ten sam problem. Kiedy dodam niestandardową czcionkę do książki czcionek, wszystko działa jak urok.
Sushant Jagtap
1
Chociaż to rozwiązanie działa w niektórych przypadkach, napotkałem również ten sam problem, co @Daniel w tym samym projekcie z tą samą rodziną czcionek. XCode musi rozwiązać ten problem.
dey.shin
16

Możesz dodać niestandardowe czcionki do książki czcionek.

Krok 1 : Kliknij Zarządzaj czcionkami. Otwiera książkę czcionek.

wprowadź opis obrazu tutaj

Krok 2 : Kliknij plus i dodaj swoje czcionki.

wprowadź opis obrazu tutaj

Następnym razem, gdy klikniesz czcionkę z przypisanym tekstem, nowo dodana czcionka również pojawi się na liście. Ale upewnij się, że Twoja niestandardowa czcionka została dodana do info.plist i zasobów pakietu.

mahbaleshwar hegde
źródło
To działa w scenorysie, ale po uruchomieniu nie pokazuje formatowania
Van
1
Formatowanie @Van? Czy możesz powiedzieć mi więcej? Kiedy to nie działa?
mahbaleshwar hegde
Muszę ustawić tekst, który jest mieszanką rgualr i pogrubioną czcionką. Użyłem rozwiązania powyżej, więc zadziałało w scenorysie, ale kiedy uruchamiam aplikację, etykieta nie pokazuje zastosowanej czcionki zamiast czcionki systemowej
Van
Czy dodałeś własne czcionki w info.plist? Następnie po prostu wydrukuj wszystkie rodziny czcionek
mahbaleshwar hegde
2
tak. Jestem w stanie ustawić niestandardową czcionkę w całej aplikacji w przypadku zwykłego tekstu, muszę ustawić przypisany tekst
Van
5

Dzięki temu wątkowi doszedłem do takiego rozwiązania:

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
}
rexsheng
źródło
1
Dobry pomysł. To naprawdę niewiarygodne, że jest zepsuty w Apple. Zadziwiający.
Fattie,
4

Moje rozwiązanie wymaga trochę obejścia. Prawdziwym rozwiązaniem jest naprawienie przez firmę Apple programu Interface Builder.

Dzięki niemu możesz zaznaczyć cały pogrubiony i pochylony tekst w narzędziu do tworzenia interfejsu za pomocą czcionki systemowej, a następnie renderować niestandardową czcionkę w czasie wykonywania. Może nie być optymalne we wszystkich przypadkach.

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

Zainspirowany tym postem

KidA
źródło
4

Zmagałem się z tym błędem: UILabel wyświetla się poprawnie w IB z niestandardową czcionką, ale nie wyświetla się poprawnie na urządzeniu lub w symulatorze (czcionka jest zawarta w projekcie i jest używana w zwykłych etykietach UIL).

Wreszcie znalazł Attributed String Creator w (Mac) App Store. Generuje kod do umieszczenia w aplikacji w odpowiednim miejscu. Fantastyczny. Nie jestem twórcą, tylko szczęśliwym użytkownikiem.

ghr
źródło
3

Napotkałem ten sam problem: zestaw czcionek atrybutu dla TextView w scenorysie nie działał w czasie wykonywania z zestawem SDK XCode 6.1 i iOS 8.

Oto jak rozwiązałem ten problem, może to być dla Ciebie obejście:

  1. otwórz inspektora atrybutów swojego widoku tekstu, zmień tekst na „Zwykły”

  2. kliknij krzyżyk, aby usunąć „wC hR” (czerwony poniżej)

    wprowadź opis obrazu tutaj

  3. zmień tekst na „Przypisane”, a następnie możesz ustawić czcionkę i rozmiar tekstu.

  4. biegnij, aby sprawdzić, czy działa
Zhihao Yang
źródło
Wygląda na to, że domyślnie nie ma wC hRustawionej właściwości, ani UILabelani UITextView.
Allen Hsu
przez xcode 6, czy ustawiłeś inny rodzaj wysokości-szerokości, np. „Zwykła szerokość | Dowolna wysokość”, „Kompaktowa szerokość | Normalna wysokość”? ponieważ mam projekt opracowany w Xcode 5 i jego przypisany widok tekstu działa nawet z SDK iOS 8, sprawdziłem tam ustawienia i stwierdziłem, że jedyną różnicą jest to, że Xcode 6 pozwala użytkownikom ustawić czcionkę dla różnych rozmiarów urządzeń, jeśli ustawisz tekst w "Równina". Ta nowa konfiguracja może być przyczyną, dla której ustawienie tekstu w opcji „przypisane”, ale czcionka nie działa.
Zhihao Yang
1
czy używasz niestandardowych czcionek? Mam na myśli te osadzone samodzielnie, a nie czcionki systemowe.
Allen Hsu
Aha, pomyślałem, że "niestandardowe" czcionki, o których wspomniałeś, to te oferowane przez Xcode, pod warunkiem, że ma czcionkę "System".
Zhihao Yang
Nie działa mi. Działa dla normalnego ciągu, ale nie dla przypisanego ciągu.
Pratik Somaiya
2

Napotkałem ten sam problem: czcionka atrybutu dla UILabel w scenorysie nie działała w czasie wykonywania. Korzystanie z tego UIFont + IBCustomFonts.m działa dla mnie https://github.com/deni2s/IBCustomFonts

Praveen Sevta
źródło
2

Spróbuj tego, to zadziała

W moim przypadku, gdy próbuję ustawić "Silversky Technology" jako tekst przypisany dla etykiety z kreatora interfejsu, nie jest on wyświetlany, gdy uruchamiam w symulatorze, ale jest wyświetlany w kreatorze interfejsów. Więc użyłem jednej sztuczki i stworzyłem czcionkę Silversky o 1 piksel większy niż tekst Technology.

Tekst atrybutu ma problem z tym samym rozmiarem czcionki, więc zmień rozmiar o 1 słowo , aby ze mną zadziałało.

Może to jest błąd xcode, ale ta sztuczka działa dla mnie.

Technologia Silversky
źródło
1

Ten sam problem.

Rozwiązany: po prostu zaznacz opcję Selectable w TextView. Bez tego mam standardową czcionkę systemową.

Maselko
źródło
1

Kliknij dwukrotnie i zainstaluj czcionkę w systemie. Będzie działać (Xcode 8.2)

Ishara Meegahawala
źródło
1
Chciałabym, żeby tak było. To nie działa dla mnie z FontAwesome.
Peter DeWeese
1

Rozwiązanie @Hamidptb działa, upewnij się, że masz poprawną nazwę czcionki (po dodaniu jej do Albumu z czcionkami)

  • Otwórz aplikację Album z czcionkami, przejdź do czcionki, a następnie naciśnij klawisze Command + I. Nazwa PostScript to nazwa czcionki, której chcesz użyć w tym miejscu:

    UILabel.appearance (). Font = UIFont (nazwa: " PostScriptName ", rozmiar: 17)

itsmcgh
źródło
0

Próbowałem uzyskać komórki tableView z tekstem zawierającym wiele akapitów. Przypisane ciągi wydawały się być sposobem na uzyskanie dodatkowej przestrzeni między akapitami (coś nieco ładniejszego niż zrobienie dwóch nowych linii w ciągu). Przeszedłem przez ten i inne posty, gdy odkryłem, że ustawienia IB nie mają zastosowania w czasie wykonywania, gdy chciałeś umieścić inny tekst w komórce.

Główną rzeczą, jaką wymyśliłem, było dodanie rozszerzenia do String (przy użyciu języka Swift), aby utworzyć przypisany ciąg o określonych cechach. W przykładzie użyto czcionki Marker Felt, ponieważ można ją łatwo odróżnić od czcionki Helvetica. Przykład pokazuje również trochę dodatkowych odstępów między akapitami, aby były one bardziej różne od siebie.

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

Następnie w moim niestandardowym tableViewCell wysyłasz żądany tekst i konwertuje go na przypisany ciąg w UILabel.

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

W kontrolerze widoku z tableView powinieneś zarejestrować swoją komórkę w viewDidLoad () - użyłem stalówki, czyli coś takiego:

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

Aby komórka obliczyła, jaka powinna być wysoka, utwórz prototypową komórkę, która jest używana do pobierania informacji o rozmiarze i nigdy nie jest dodawana do tableView. Tak więc w zmiennych kontrolera widoku:

var prototypeSummaryCell : MarkerFeltCell? = nil

Następnie w (prawdopodobnie przesłonięcie - w zależności od kontrolera widoku) 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 {  // ...

W powyższym kodzie prototypeCell zostanie wypełnione, gdy będzie to potrzebne po raz pierwszy. PrototypeCell jest następnie używany do obliczenia wysokości komórki po przejściu przez proces autodopasowania. Będziesz musiał zaokrąglić wysokość za pomocą funkcji ceil (). Dodałem też trochę dodatkowego krówki.

Ostatnim bitem kodu jest sposób konfiguracji tekstu komórki. W tym przykładzie po prostu:

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

Tutaj jest również ujęcie stalówki. Przypięto etykietę do krawędzi komórki (z wymaganym marginesem), ale zastosowano ograniczenie „Większe niż lub równe” z priorytetem mniejszym niż „Wymagany” dla ograniczenia dolnego.

Ograniczenia komórek

Ustaw czcionkę etykiety na Attributed. Rzeczywista czcionka IB nie miała znaczenia.

LabelFont

Wynik w tym przypadku:

CellResults

anorskdev
źródło
0

W przypadku przypisanego ciągu znaków można dodać niestandardową czcionkę do listy czcionek jako - Kliknij ikonę czcionki, co spowoduje wyświetlenie następującego okna dialogowego. W następnym oknie dialogowym możesz dodać własną kategorię lub istniejącą dla niestandardowej czcionki. okno dialogowe z przypisaną czcionką

Po kliknięciu Zarządzaj czcionkami otwiera się następujące okno dialogowe wyboru kategorii w utworzonej lub istniejącej. Kliknij znak +, aby dodać czcionkę do kategorii. Okno dialogowe Zarządzaj czcionkami

Sunil Singh
źródło
0

to ma proste i szybkie rozwiązanie i to działa w moim przypadku. tym rozwiązaniem jest dodanie linii kodu do funkcji didFinishLaunchingWithOptions w pliku AppDelegate.swift:

dla textViews :

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

dla etykiet :

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

a dla reszty UiView takie jak te dwa ☝️

Hamid Reza Ansari
źródło
0

Dla każdego, kto stosuje niestandardowe czcionki do przypisanego ciągu w kodzie: Spróbuj ustawić go w viewDidLayoutSubviews. Mój błąd polegał na tym viewDidLoad, że nie zostanie to zastosowane.

sergey.syrotynin
źródło