Строка с атрибутами с пользовательскими шрифтами в раскадровке загружается неправильно

100

В нашем проекте мы используем нестандартные шрифты. Он хорошо работает в Xcode 5. В Xcode 6 он работает с обычным текстом, приписывая строку в коде. Но все эти приписанные строки, установленные в раскадровке, возвращаются к Helvetica при запуске на симуляторе или устройстве, хотя в раскадровке они выглядят нормально.

Я не уверен, что это ошибка Xcode 6 или iOS 8 SDK, или способ использования пользовательских шрифтов изменен в Xcode 6 / iOS 8?

Аллен Хсу
источник
Здесь та же проблема. Хотел бы знать, что случилось.
obeattie
1
На данный момент мы создали настраиваемый UILabel с именем GLMarkdownLabel и экспортировали некоторые свойства с помощью IBInspectable, затем установили строки уценки в раскадровке и преобразовали строки уценки обратно в строки с атрибутами, когда проснулись от пера.
Аллен Хсу
Теперь это долгосрочное решение, надеюсь, Apple исправит эту ошибку в следующей версии Xcode.
Аллен Хсу
Ой, такая хрень. Спасибо, что сообщили нам, что это не единичная проблема. Есть радар?
obeattie
1
Наше обходное решение в конечном итоге было возвращено к использованию IBCustomFonts для наших меток с атрибутами.
yonix 02

Ответы:

30

Исправление для меня заключалось в использовании IBDesignableкласса:

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

Предоставляя вам это в Интерфейсном Разработчике:

Пользовательский шрифт Interface Builder с приписанной строкой

Вы можете настроить атрибутную строку так же, как обычно, но вам придется снова установить размер шрифта и семейство шрифтов в новых доступных свойствах.

Поскольку Interface Builder по умолчанию работает с настраиваемым шрифтом, это приводит к тому, что вы видите то, что получаете , что я предпочитаю при создании приложений.

Заметка

Причина, по которой я использую это вместо простой версии, заключается в том, что я устанавливаю свойства атрибутированной метки, такие как межстрочный интервал, которые недоступны при использовании простого стиля.

Антуан
источник
1
Ваше решение поддерживает только одно семейство шрифтов и размер для метки, тогда почему бы вместо этого просто не использовать простой текст?
Allen Hsu
Точно так же мы @IBInspectableвременно используем атрибуты вместо шрифта и размера. У нас есть markdownTextсвойство, потому что в большинстве случаев мы используем строку с атрибутами для полужирного или подчеркнутого текста. Затем проанализируйте текст уценки на атрибутивную строку с информацией о шрифте и размере, установленной для обычного текста.
Аллен Сюй
@AllenHsu, ты прав. Я не упоминал об этом, но я использую приписанный межстрочный интервал для своего ярлыка. Конечно, иначе вы бы просто использовали простой стиль :)
Антуан
хороший момент, мы также экспортировали lineSpacing: p Думаю, я приму ваш ответ, поскольку на самом деле это ошибка в Xcode, и на данный момент лучшего решения нет. Подождем следующей версии Xcode.
Аллен Хсу
2
Это не сработает, если я хочу
выделить
28

Самый простой ответ - перетащить шрифты в FontBook. Если шрифты находятся в вашем проекте, но отсутствуют в FontBook вашего компьютера, IB иногда не может найти их. Странно, но несколько раз мне удавалось.

Алан Скарпа
источник
17
Хотя это позволяет Xcode выбирать собственный шрифт, на самом деле это не работает. Во время выполнения шрифт не будет использоваться так, как вы ожидаете.
Дэниел
К сожалению, мне не удалось найти обходной путь. Лучшее, что я мог сделать, это зарегистрировать ошибку в Apple.
Daniel
Да, это исправление. Моя раскадровка была разработана другим разработчиком, svn update ok, но я так и не получил шрифт в пользовательском интерфейсе. Шрифт был в ресурсах, но не отображался в пользовательском интерфейсе устройства / симулятора. Поскольку он использует атрибутивную строку, я должен иметь ее в Книге шрифтов. Это решает проблему.
Karim
Да. это помогает мне решить ту же проблему. Когда я добавляю собственный шрифт в книгу шрифтов, все работает как шарм.
Sushant Jagtap
1
Хотя это решение работает в некоторых случаях, я также столкнулся с той же проблемой, что и @Daniel, в том же проекте с тем же семейством шрифтов. XCode необходимо решить эту проблему.
dey.shin
16

Вы можете добавлять собственные шрифты в книгу шрифтов.

Шаг 1 : нажмите «Управление шрифтами». Он открывает книгу шрифтов.

введите описание изображения здесь

Шаг 2 : Щелкните плюс и добавьте шрифты.

введите описание изображения здесь

В следующий раз, когда вы нажмете на шрифт с соответствующим текстом, новый добавленный шрифт также отобразится в списке. Но убедитесь, что ваш собственный шрифт добавлен в info.plist и ресурсы пакета.

Махбалешвар Хегде
источник
Это работает в раскадровке, но после запуска не показывает форматирование
Ван
1
@Van форматирование? Не могли бы вы рассказать мне больше? Когда не работает?
mahbaleshwar hegde,
Мне нужно установить текст, который сочетает в себе rgualr и жирный шрифт. Я использовал решение, указанное выше, поэтому оно работало в раскадровке, но когда я запускаю приложение, на ярлыке не отображается примененный шрифт, а отображается системный шрифт
Ван
Вы добавляли свои собственные шрифты в info.plist? После этого просто распечатайте все семейства шрифтов
mahbaleshwar hegde
2
да. Я могу установить собственный шрифт для всего приложения в случае обычного текста, мне нужно установить для текста с атрибутами
Ван,
5

Благодаря этой теме я пришел к такому решению:

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
источник
1
Хорошая идея. Это действительно невероятно, что в Apple сломано. Поразительно.
Fattie
4

Мое решение - это небольшая работа. Настоящее решение для Apple - исправить Interface Builder.

С его помощью вы можете пометить весь полужирный и курсивный текст в построителе интерфейса с помощью системного шрифта, а затем во время выполнения визуализировать свой собственный шрифт. Не во всех случаях может быть оптимальным.

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

На основе этого поста

KidA
источник
4

Я боролся с этой ошибкой: UILabel правильно отображается в IB с пользовательским шрифтом, но не отображается правильно на устройстве или симуляторе (шрифт включен в проект и используется в простых UILabels).

Наконец нашел Attributed String Creator в (Mac) App Store. Создает код для размещения в вашем приложении в нужном месте. Фантастика. Я не создатель, просто счастливый пользователь.

гр
источник
3

Возникла та же проблема: шрифт атрибута, установленный для TextView в раскадровке, не работал во время выполнения с XCode 6.1 и iOS 8 SDK.

Вот как я решил эту проблему, может быть для вас обходной путь:

  1. откройте инспектор атрибутов вашего текстового представления, измените текст на "Обычный"

  2. нажмите на крестик, чтобы удалить "wC hR" (красный внизу)

    введите описание изображения здесь

  3. измените текст на «Приписанный», а затем вы можете установить шрифт и размер текста.

  4. беги проверить, работает ли он
Чжихао Ян
источник
Похоже, что по умолчанию никаких wC hRсвойств не задано, ни, UILabelни UITextView.
Аллен Хсу
с помощью xcode 6, вы установили другой тип высоты-ширины, например «Обычная ширина | Любая высота», «Компактная ширина | Обычная высота»? поскольку у меня есть проект, разработанный в Xcode 5, и его атрибутированное текстовое представление работает даже с iOS 8 SDK, я проверил там настройки и обнаружил, что единственная разница в том, что Xcode 6 позволяет пользователям устанавливать шрифт для разных размеров устройств, если вы устанавливаете текст в «Обычный». Эта новая конфигурация может быть причиной того, что установка текста в "приписанный", но шрифт не работает.
Чжихао Ян
1
вы используете нестандартные шрифты? Я имею в виду встроенные, а не системные шрифты.
Аллен Хсу
Ага, я подумал, что «Custom» шрифты, о которых вы упомянули, - это те, которые предлагает Xcode при условии, что у него есть шрифт «System».
Чжихао Ян
Это не работает для меня. Он работает для обычной строки, но не для строки с атрибутами.
Pratik Somaiya
2

Возникла та же проблема: шрифт атрибута для UILabel в раскадровке не работал во время выполнения. Использование этого UIFont + IBCustomFonts.m работает для меня https://github.com/deni2s/IBCustomFonts

Правеен Севта
источник
2

Попробуйте, это сработает

В моем случае, когда я пытаюсь установить «Silversky Technology» в качестве атрибутивного текста для метки из построителя интерфейса, он не отображается, когда я запускаю в симуляторе, но отображается в построителе интерфейса. Итак, я использовал один трюк: сделал шрифт Silversky на 1 пиксель больше, чем текст Technology.

У текста атрибута есть проблема с тем же размером шрифта, поэтому измените размер 1 слова, эта штука работает со мной.

Может быть, это ошибка xcode, но этот трюк у меня работает.

Silversky Technology
источник
1

Та же проблема.

Решено: просто отметьте "Выбираемый" в TextView. Без этого у меня стандартный системный шрифт.

Маселко
источник
1

Дважды щелкните и установите шрифт в систему. Он будет работать (Xcode 8.2)

Ишара Мигахавала
источник
1
Я бы так хотел. У меня не работает FontAwesome.
Питер
1

Решение @Hamidptb работает, убедитесь, что вы получили правильное имя шрифта (после добавления его в книгу шрифтов)

  • Откройте приложение Font Book, перейдите к своему шрифту и нажмите Command + I. Имя PostScript - это имя шрифта, которое вы хотите здесь использовать:

    UILabel.appearance (). Font = UIFont (имя: " PostScriptName ", размер: 17)

itsmcgh
источник
0

Я пытался получить ячейки tableView с текстом, имеющим несколько абзацев. Строки с атрибутами, казалось, были способом получить дополнительное пространство между абзацами (что-то немного приятнее, чем два перевода строки в строку). Я наткнулся на этот и другие сообщения, когда обнаружил, что настройки IB не применяются во время выполнения, когда вы хотите поместить другой текст в ячейку.

Главное, что я придумал, - это добавить расширение к String (используя Swift) для создания атрибутированной строки с определенными характеристиками. В данном примере используется шрифт Marker Felt, так как его легко отличить от Helvetica. В примере также показан небольшой дополнительный интервал между абзацами, чтобы сделать их более отличными друг от друга.

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

Затем в моем настраиваемом tableViewCell вы отправляете ему нужный текст, и он преобразует его в строку с атрибутами в UILabel.

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

В контроллере представления с tableView вы должны зарегистрировать свою ячейку в viewDidLoad () - я использовал перо, поэтому что-то вроде:

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

Чтобы ячейка определяла, какой высоты она должна быть, создайте ячейку-прототип, которая используется для получения информации о размере и никогда не добавляется в tableView. Итак, в переменных вашего контроллера представления:

var prototypeSummaryCell : MarkerFeltCell? = nil

Затем в (возможно, переопределите - в зависимости от вашего контроллера представления) 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 {  // ...

В приведенном выше коде prototypeCell будет заполнен при первой необходимости. Затем prototypeCell используется для определения высоты ячейки после прохождения процесса автоматического изменения размера. Вам нужно будет округлить высоту с помощью функции ceil (). Я также добавил дополнительный фактор выдумки.

Последний бит кода - это то, как вы настраиваете текст для ячейки. В этом примере просто:

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

Кроме того, вот снимок пера. Прикрепил метку к краям ячейки (с желаемым полем), но использовал ограничение «Больше или равно» с приоритетом ниже «Обязательный» для нижнего ограничения.

Ограничения ячейки

Установите для метки шрифт «Приписанный». Фактический шрифт IB не имел значения.

LabelFont

Результат в таком случае:

CellResults

Anorskdev
источник
0

В случае атрибутированной строки вы можете добавить собственный шрифт в список шрифтов как - Щелкните значок шрифта, появится следующий диалог. В следующем диалоге вы можете добавить свою собственную категорию или существующую категорию для пользовательского шрифта. диалоговое окно с атрибутированным шрифтом

После нажатия на « Управление шрифтами» открывается следующий диалог выбора категории в созданной или существующей. Щелкните знак +, чтобы добавить шрифт в категорию. Диалог управления шрифтом

Сунил Сингх
источник
0

это простое и быстрое решение, и это работает в моем случае. это решение добавляет строку кода в функцию didFinishLaunchingWithOptions в файле AppDelegate.swift:

для textViews :

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

для этикеток :

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

а для остального UiView вроде этих двух ☝️

Хамид Реза Ансари
источник
0

Для тех, кто применяет пользовательские шрифты к строке с атрибутами в коде: попробуйте установить его viewDidLayoutSubviews. Моя ошибка заключалась в том, что это было сделано viewDidLoad, это не будет применяться там.

сергей сыротинин
источник