Как сделать приписанную строку, используя Swift?

316

Я пытаюсь сделать простой калькулятор кофе. Мне нужно отобразить количество кофе в граммах. Символ «g» для граммов должен быть прикреплен к моей UILabel, которую я использую для отображения суммы. Числа в UILabel динамически меняются с пользовательским вводом, но мне нужно добавить строчную букву «g» в конце строки, которая отформатирована иначе, чем номера обновлений. «G» необходимо прикрепить к номерам, чтобы при изменении размера и положения номера «g» перемещался вместе с числами. Я уверен, что эта проблема была решена раньше, поэтому ссылка в правильном направлении была бы полезна, так как я погуглил свое маленькое сердце.

Я искал в документации атрибутивную строку и даже загрузил «Attributed String Creator» из магазина приложений, но полученный код находится в Objective-C, и я использую Swift. То, что было бы замечательно и, вероятно, полезно для других разработчиков, изучающих этот язык, - это яркий пример создания собственного шрифта с настраиваемыми атрибутами с использованием приписанной строки в Swift. Документация для этого очень запутанная, так как нет четкого пути, как это сделать. Мой план состоит в том, чтобы создать приписанную строку и добавить ее в конец моей строки coffeeAmount.

var coffeeAmount: String = calculatedCoffee + attributedText

Где вычисленный кофе - это Int, преобразованный в строку, а "attribuText" - это строчная буква "g" с настроенным шрифтом, который я пытаюсь создать. Может быть, я иду по этому пути неправильно. Любая помощь приветствуется!

dcbenji
источник

Ответы:

970

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

Этот ответ был обновлен для Swift 4.2.

Краткий справочник

Общая форма создания и установки приписанной строки выглядит следующим образом. Вы можете найти другие общие варианты ниже.

// create attributed string
let myString = "Swift Attributed String"
let myAttribute = [ NSAttributedString.Key.foregroundColor: UIColor.blue ]
let myAttrString = NSAttributedString(string: myString, attributes: myAttribute) 

// set attributed text on a UILabel
myLabel.attributedText = myAttrString

Цвет текста

let myAttribute = [ NSAttributedString.Key.foregroundColor: UIColor.blue ]

Фоновый цвет

let myAttribute = [ NSAttributedString.Key.backgroundColor: UIColor.yellow ]

Шрифт

let myAttribute = [ NSAttributedString.Key.font: UIFont(name: "Chalkduster", size: 18.0)! ]

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

let myAttribute = [ NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue ]

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

let myShadow = NSShadow()
myShadow.shadowBlurRadius = 3
myShadow.shadowOffset = CGSize(width: 3, height: 3)
myShadow.shadowColor = UIColor.gray

let myAttribute = [ NSAttributedString.Key.shadow: myShadow ]

Остальная часть этого поста дает более подробную информацию для тех, кто заинтересован.


Атрибуты

Строковые атрибуты - это просто словарь в форме [NSAttributedString.Key: Any], где NSAttributedString.Keyэто имя ключа атрибута и Anyзначение некоторого типа. Значением может быть шрифт, цвет, целое число или что-то еще. В Swift есть много стандартных атрибутов, которые уже были предопределены. Например:

  • имя ключа:, NSAttributedString.Key.fontзначение: aUIFont
  • имя ключа:, NSAttributedString.Key.foregroundColorзначение: aUIColor
  • имя ключа:, NSAttributedString.Key.linkзначение: NSURLилиNSString

Есть много других. Смотрите эту ссылку для более. Вы даже можете создавать свои собственные атрибуты, такие как:

  • имя ключа:, NSAttributedString.Key.myNameзначение: какой-то тип.
    если вы делаете расширение :

    extension NSAttributedString.Key {
        static let myName = NSAttributedString.Key(rawValue: "myCustomAttributeKey")
    }

Создание атрибутов в Swift

Вы можете объявить атрибуты так же, как и любой другой словарь.

// single attributes declared one at a time
let singleAttribute1 = [ NSAttributedString.Key.foregroundColor: UIColor.green ]
let singleAttribute2 = [ NSAttributedString.Key.backgroundColor: UIColor.yellow ]
let singleAttribute3 = [ NSAttributedString.Key.underlineStyle: NSUnderlineStyle.double.rawValue ]

// multiple attributes declared at once
let multipleAttributes: [NSAttributedString.Key : Any] = [
    NSAttributedString.Key.foregroundColor: UIColor.green,
    NSAttributedString.Key.backgroundColor: UIColor.yellow,
    NSAttributedString.Key.underlineStyle: NSUnderlineStyle.double.rawValue ]

// custom attribute
let customAttribute = [ NSAttributedString.Key.myName: "Some value" ]

Обратите внимание, что rawValueэто было необходимо для значения стиля подчеркивания.

Поскольку атрибуты являются просто словарями, вы также можете создать их, создав пустой словарь и добавив в него пары ключ-значение. Если значение будет содержать несколько типов, то вы должны использовать Anyв качестве типа. Вот multipleAttributesпример сверху, воссозданный таким образом:

var multipleAttributes = [NSAttributedString.Key : Any]()
multipleAttributes[NSAttributedString.Key.foregroundColor] = UIColor.green
multipleAttributes[NSAttributedString.Key.backgroundColor] = UIColor.yellow
multipleAttributes[NSAttributedString.Key.underlineStyle] = NSUnderlineStyle.double.rawValue

Приписанные Строки

Теперь, когда вы понимаете атрибуты, вы можете создавать атрибутные строки.

инициализация

Есть несколько способов создания приписанных строк. Если вам просто нужна строка только для чтения, вы можете использовать NSAttributedString. Вот несколько способов его инициализации:

// Initialize with a string only
let attrString1 = NSAttributedString(string: "Hello.")

// Initialize with a string and inline attribute(s)
let attrString2 = NSAttributedString(string: "Hello.", attributes: [NSAttributedString.Key.myName: "A value"])

// Initialize with a string and separately declared attribute(s)
let myAttributes1 = [ NSAttributedString.Key.foregroundColor: UIColor.green ]
let attrString3 = NSAttributedString(string: "Hello.", attributes: myAttributes1)

Если вам потребуется изменить атрибуты или содержимое строки позже, вы должны использовать NSMutableAttributedString. Декларации очень похожи:

// Create a blank attributed string
let mutableAttrString1 = NSMutableAttributedString()

// Initialize with a string only
let mutableAttrString2 = NSMutableAttributedString(string: "Hello.")

// Initialize with a string and inline attribute(s)
let mutableAttrString3 = NSMutableAttributedString(string: "Hello.", attributes: [NSAttributedString.Key.myName: "A value"])

// Initialize with a string and separately declared attribute(s)
let myAttributes2 = [ NSAttributedString.Key.foregroundColor: UIColor.green ]
let mutableAttrString4 = NSMutableAttributedString(string: "Hello.", attributes: myAttributes2)

Изменение атрибутной строки

В качестве примера давайте создадим приписанную строку в верхней части этого поста.

Сначала создайте NSMutableAttributedStringс новым атрибутом шрифта.

let myAttribute = [ NSAttributedString.Key.font: UIFont(name: "Chalkduster", size: 18.0)! ]
let myString = NSMutableAttributedString(string: "Swift", attributes: myAttribute )

Если вы работаете вместе, установите для приписанной строки значение UITextView(или UILabel), например:

textView.attributedText = myString

Вы не используете textView.text.

Вот результат:

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

Затем добавьте еще одну атрибутивную строку, для которой не установлены никакие атрибуты. (Обратите внимание, что, хотя я letи заявлял myStringвыше, я все еще могу изменить его, потому что он является NSMutableAttributedString. Это кажется мне довольно не быстрым, и я не удивлюсь, если это изменится в будущем. Оставьте мне комментарий, когда это произойдет.)

let attrString = NSAttributedString(string: " Attributed Strings")
myString.append(attrString)

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

Далее мы просто выберем слово «Strings», которое начинается с индекса 17и имеет длину 7. Обратите внимание, что это NSRangeи не Swift Range. (См. Этот ответ для получения дополнительной информации о диапазонах.) Этот addAttributeметод позволяет поместить имя ключа атрибута в первое место, значение атрибута во второе место и диапазон в третье место.

var myRange = NSRange(location: 17, length: 7) // range starting at location 17 with a lenth of 7: "Strings"
myString.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.red, range: myRange)

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

Наконец, давайте добавим цвет фона. Для разнообразия, давайте использовать addAttributesметод (обратите внимание s). Я мог бы добавить несколько атрибутов одновременно с этим методом, но я просто добавлю один снова.

myRange = NSRange(location: 3, length: 17)
let anotherAttribute = [ NSAttributedString.Key.backgroundColor: UIColor.yellow ]
myString.addAttributes(anotherAttribute, range: myRange)

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

Обратите внимание, что атрибуты в некоторых местах перекрываются. Добавление атрибута не перезаписывает атрибут, который уже существует.

Связанный

Дальнейшее чтение

Suragch
источник
4
Обратите внимание, что вы можете объединить несколько стилей для подчеркивания, например,NSUnderlineStyleAttributeName: NSUnderlineStyle.StyleSingle.rawValue | NSUnderlineStyle.PatternDot.rawValue
beeb
3
Вы не можете использовать appendAttributedString для NSAttributedString, это должно быть на NSMutableAttributedString, можете ли вы обновить свой ответ, чтобы отразить это?
Джозеф Астрахань
3
1) Супер спасибо за ваш ответ. 2) Я бы посоветовал вам разместить textView.atrributedtText = myStringили myLabel.attributedText = myStringв начале вашего ответа. Как новичок я просто делал myLabel.textи не думал, что мне нужно было пройти через все ваши ответы. ** 3) ** Значит ли это, что вы можете иметь только один из них attributedTextили textчто иметь их обоих было бы бессмысленно? 4) Я рекомендую вам также включить lineSpacingпример, подобный этому, в свой ответ, так как он очень полезен. 5) ачаар дахин
Мед
1
Разница между добавлением и добавлением сначала сбивала с толку. appendAttributedStringэто как «Конкатенация строк». addAttributeдобавляет новый атрибут в вашу строку.
Honey
2
@Daniel, addAttributeэто метод NSMutableAttributedString. Вы правы, что вы не можете использовать его с Stringили NSAttributedString. (Проверьте myStringопределение в разделе « Изменение строки атрибута » в этом посте. Я думаю, что отбросил вас, потому что я также использовал myStringимя переменной в первой части поста, где она была NSAttributedString.)
Suragch
114

Swift использует то же, NSMutableAttributedStringчто и Obj-C. Вы создаете его, передавая вычисленное значение в виде строки:

var attributedString = NSMutableAttributedString(string:"\(calculatedCoffee)")

Теперь создайте приписанную gстроку (хе). Примечание: UIFont.systemFontOfSize(_) теперь это сбойный инициализатор, поэтому его нужно развернуть, прежде чем вы сможете его использовать:

var attrs = [NSFontAttributeName : UIFont.systemFontOfSize(19.0)!]
var gString = NSMutableAttributedString(string:"g", attributes:attrs)

И затем добавьте это:

attributedString.appendAttributedString(gString)

Затем вы можете настроить UILabel для отображения NSAttributedString следующим образом:

myLabel.attributedText = attributedString
NRitH
источник
//Part 1 Set Up The Lower Case g var coffeeText = NSMutableAttributedString(string:"\(calculateCoffee())") //Part 2 set the font attributes for the lower case g var coffeeTypeFaceAttributes = [NSFontAttributeName : UIFont.systemFontOfSize(18)] //Part 3 create the "g" character and give it the attributes var coffeeG = NSMutableAttributedString(string:"g", attributes:coffeeTypeFaceAttributes) Когда я устанавливаю свой UILabel.text = coffeeText, я получаю сообщение об ошибке «NSMutableAttributedString не конвертируется в« String ». Есть ли способ заставить UILabel принимать NSMutableAttributedString?
dcbenji
11
Если у вас есть приписанная строка, вам нужно установить свойство attributeText метки вместо ее текстового свойства.
NRitH
1
Это сработало правильно, и моя строчная буква "g" теперь добавляется к концу текста о количестве кофе
dcbenji
2
По какой-то причине я получаю сообщение об ошибке «дополнительный аргумент в вызове» в моей строке с NSAttributedString. Это происходит только тогда, когда я переключаю UIFont.systemFontOfSize (18) на UIFont (имя: «Arial», размер: 20). Любые идеи?
Unome
UIFont (name: size :) - сбойный инициализатор и может возвращать ноль. Вы можете явно развернуть его, добавив! в конце или свяжите его с переменной с помощью оператора if / let, прежде чем вставить его в словарь.
Пепел
21

Версия Xcode 6 :

let attriString = NSAttributedString(string:"attriString", attributes:
[NSForegroundColorAttributeName: UIColor.lightGrayColor(), 
            NSFontAttributeName: AttriFont])

Версия Xcode 9.3 :

let attriString = NSAttributedString(string:"attriString", attributes:
[NSAttributedStringKey.foregroundColor: UIColor.lightGray, 
            NSAttributedStringKey.font: AttriFont])

Xcode 10, iOS 12, Swift 4 :

let attriString = NSAttributedString(string:"attriString", attributes:
[NSAttributedString.Key.foregroundColor: UIColor.lightGray, 
            NSAttributedString.Key.font: AttriFont])
harthoo
источник
20

Свифт 4:

let attributes = [NSAttributedStringKey.font: UIFont(name: "HelveticaNeue-Bold", size: 17)!, 
                  NSAttributedStringKey.foregroundColor: UIColor.white]
Адам Бардон
источник
не компилируетсяType 'NSAttributedStringKey' (aka 'NSString') has no member 'font'
bibscy
Я только что попробовал его в новейшем XCode (10 бета 6) и он компилируется, вы уверены, что используете Swift 4?
Адам Бардон
Я использую Swift 3
bibscy
4
Ну, вот в чем проблема, мой ответ имеет жирный заголовок «Swift 4», я настоятельно рекомендую вам обновить его до Swift 4
Адам Бардон
@bibscy вы можете использовать NSAttributedString.Key. ***
Хатим
19

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

Если вы хотите создать строку с четырьмя разными цветами и разными шрифтами, используя SwiftyAttributes:

let magenta = "Hello ".withAttributes([
    .textColor(.magenta),
    .font(.systemFont(ofSize: 15.0))
    ])
let cyan = "Sir ".withAttributes([
    .textColor(.cyan),
    .font(.boldSystemFont(ofSize: 15.0))
    ])
let green = "Lancelot".withAttributes([
    .textColor(.green),
    .font(.italicSystemFont(ofSize: 15.0))

    ])
let blue = "!".withAttributes([
    .textColor(.blue),
    .font(.preferredFont(forTextStyle: UIFontTextStyle.headline))

    ])
let finalString = magenta + cyan + green + blue

finalString покажет как

Показывает как изображение

MendyK
источник
15

Swift: xcode 6.1

    let font:UIFont? = UIFont(name: "Arial", size: 12.0)

    let attrString = NSAttributedString(
        string: titleData,
        attributes: NSDictionary(
            object: font!,
            forKey: NSFontAttributeName))
Винод Джоши
источник
10

Лучший способ приблизиться к Attributed Strings на iOS - это использовать встроенный текстовый редактор Attributed Text в конструкторе интерфейса и избежать ненужного жесткого кодирования NSAtrributedStringKeys в ваших исходных файлах.

Позже вы можете динамически заменять placehoderls во время выполнения, используя это расширение:

extension NSAttributedString {
    func replacing(placeholder:String, with valueString:String) -> NSAttributedString {

        if let range = self.string.range(of:placeholder) {
            let nsRange = NSRange(range,in:valueString)
            let mutableText = NSMutableAttributedString(attributedString: self)
            mutableText.replaceCharacters(in: nsRange, with: valueString)
            return mutableText as NSAttributedString
        }
        return self
    }
}

Добавьте метку раскадровки с атрибутивным текстом, похожим на этот.

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

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

label.attributedText = initalAttributedString.replacing(placeholder: "<price>", with: newValue)

Обязательно сохраните в initalAttributedString исходное значение.

Вы можете лучше понять этот подход, прочитав эту статью: https://medium.com/mobile-appetite/text-attributes-on-ios-the-effortless-approach-ff086588173e

Эфраим
источник
Это было очень полезно для моего случая, когда у меня была раскадровка и я просто хотел добавить жирный шрифт к части строки в метке. Гораздо проще, чем настраивать все атрибуты вручную.
Марк Аттинаси
Это расширение раньше работало для меня отлично, но в Xcode 11 оно разбило мое приложение на let nsRange = NSRange(range,in:valueString)линии.
Лукас П.
9

Swift 2.0

Вот образец:

let newsString: NSMutableAttributedString = NSMutableAttributedString(string: "Tap here to read the latest Football News.")
newsString.addAttributes([NSUnderlineStyleAttributeName: NSUnderlineStyle.StyleDouble.rawValue], range: NSMakeRange(4, 4))
sampleLabel.attributedText = newsString.copy() as? NSAttributedString

Swift 5.x

let newsString: NSMutableAttributedString = NSMutableAttributedString(string: "Tap here to read the latest Football News.")
newsString.addAttributes([NSAttributedString.Key.underlineStyle: NSUnderlineStyle.double.rawValue], range: NSMakeRange(4, 4))
sampleLabel.attributedText = newsString.copy() as? NSAttributedString

ИЛИ

let stringAttributes = [
    NSFontAttributeName : UIFont(name: "Helvetica Neue", size: 17.0)!,
    NSUnderlineStyleAttributeName : 1,
    NSForegroundColorAttributeName : UIColor.orangeColor(),
    NSTextEffectAttributeName : NSTextEffectLetterpressStyle,
    NSStrokeWidthAttributeName : 2.0]
let atrributedString = NSAttributedString(string: "Sample String: Attributed", attributes: stringAttributes)
sampleLabel.attributedText = atrributedString
AG
источник
8

Хорошо работает в бета 6

let attrString = NSAttributedString(
    string: "title-title-title",
    attributes: NSDictionary(
       object: NSFont(name: "Arial", size: 12.0), 
       forKey: NSFontAttributeName))
Андрей
источник
7

Я создал онлайн-инструмент, который решит вашу проблему! Вы можете написать свою строку и применить стили графически, и инструмент даст вам код target-c и swift для генерации этой строки.

Также с открытым исходным кодом, так что не стесняйтесь расширять его и отправлять PR.

Инструмент Трансформер

Github

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

Andres
источник
Не работает для меня Он просто заключает все в скобки без применения какого-либо стиля.
Даниэль Спрингер
6

Swift 5 и выше

   let attributedString = NSAttributedString(string:"targetString",
                                   attributes:[NSAttributedString.Key.foregroundColor: UIColor.lightGray,
                                               NSAttributedString.Key.font: UIFont(name: "Arial", size: 18.0) as Any])
мидхун р
источник
5
func decorateText(sub:String, des:String)->NSAttributedString{
    let textAttributesOne = [NSAttributedStringKey.foregroundColor: UIColor.darkText, NSAttributedStringKey.font: UIFont(name: "PTSans-Bold", size: 17.0)!]
    let textAttributesTwo = [NSAttributedStringKey.foregroundColor: UIColor.black, NSAttributedStringKey.font: UIFont(name: "PTSans-Regular", size: 14.0)!]

    let textPartOne = NSMutableAttributedString(string: sub, attributes: textAttributesOne)
    let textPartTwo = NSMutableAttributedString(string: des, attributes: textAttributesTwo)

    let textCombination = NSMutableAttributedString()
    textCombination.append(textPartOne)
    textCombination.append(textPartTwo)
    return textCombination
}

//Реализация

cell.lblFrom.attributedText = decorateText(sub: sender!, des: " - \(convertDateFormatShort3(myDateString: datetime!))")
Йогеш Тандель
источник
4

Swift 4

let attributes = [NSAttributedStringKey.font : UIFont(name: CustomFont.NAME_REGULAR.rawValue, size: CustomFontSize.SURVEY_FORM_LABEL_SIZE.rawValue)!]

let attributedString : NSAttributedString = NSAttributedString(string: messageString, attributes: attributes)

Вам нужно удалить необработанное значение в swift 4

Неху
источник
3

Для меня вышеупомянутые решения не работали при установке определенного цвета или свойства.

Это сработало:

let attributes = [
    NSFontAttributeName : UIFont(name: "Helvetica Neue", size: 12.0)!,
    NSUnderlineStyleAttributeName : 1,
    NSForegroundColorAttributeName : UIColor.darkGrayColor(),
    NSTextEffectAttributeName : NSTextEffectLetterpressStyle,
    NSStrokeWidthAttributeName : 3.0]

var atriString = NSAttributedString(string: "My Attributed String", attributes: attributes)
swennemen
источник
3

Swift 2.1 - Xcode 7

let labelFont = UIFont(name: "HelveticaNeue-Bold", size: 18)
let attributes :[String:AnyObject] = [NSFontAttributeName : labelFont!]
let attrString = NSAttributedString(string:"foo", attributes: attributes)
myLabel.attributedText = attrString
Алессандро Орнано
источник
Какие изменения были внесены между Swift 2.0 и 2.1?
Сурагч
3

Используйте этот пример кода. Это очень короткий код для достижения ваших требований. Это работает для меня.

let attributes = [NSAttributedStringKey.font : UIFont(name: CustomFont.NAME_REGULAR.rawValue, size: CustomFontSize.SURVEY_FORM_LABEL_SIZE.rawValue)!]

let attributedString : NSAttributedString = NSAttributedString(string: messageString, attributes: attributes)
VipinYadav
источник
2
extension UILabel{
    func setSubTextColor(pSubString : String, pColor : UIColor){    
        let attributedString: NSMutableAttributedString = self.attributedText != nil ? NSMutableAttributedString(attributedString: self.attributedText!) : NSMutableAttributedString(string: self.text!);

        let range = attributedString.mutableString.range(of: pSubString, options:NSString.CompareOptions.caseInsensitive)
        if range.location != NSNotFound {
            attributedString.addAttribute(NSForegroundColorAttributeName, value: pColor, range: range);
        }
        self.attributedText = attributedString
    }
}
Дипак Панчасара
источник
cell.IBLabelGuestAppointmentTime.text = "\ n \ nGuest1 \ n8: 00 am \ n \ nGuest2 \ n9: 00Am \ n \ n" ячейка. .setSubTextColor (pSubString: "Guest2", pColor: UIColor.red)
Дипак Панчасара,
1
Добро пожаловать в ТАК. Пожалуйста, отформатируйте свой код и добавьте некоторые объяснения / контекст к вашему ответу. Смотрите: stackoverflow.com/help/how-to-answer
Уве Алнер
2

Атрибуты могут быть установлены непосредственно в Swift 3 ...

    let attributes = NSAttributedString(string: "String", attributes: [NSFontAttributeName : UIFont(name: "AvenirNext-Medium", size: 30)!,
         NSForegroundColorAttributeName : UIColor .white,
         NSTextEffectAttributeName : NSTextEffectLetterpressStyle])

Затем используйте переменную в любом классе с атрибутами

Себастьян
источник
2

Swift 4.2

extension UILabel {

    func boldSubstring(_ substr: String) {
        guard substr.isEmpty == false,
            let text = attributedText,
            let range = text.string.range(of: substr, options: .caseInsensitive) else {
                return
        }
        let attr = NSMutableAttributedString(attributedString: text)
        let start = text.string.distance(from: text.string.startIndex, to: range.lowerBound)
        let length = text.string.distance(from: range.lowerBound, to: range.upperBound)
        attr.addAttributes([NSAttributedStringKey.font: UIFont.boldSystemFont(ofSize: self.font.pointSize)],
                           range: NSMakeRange(start, length))
        attributedText = attr
    }
}
Дебаприо Б
источник
Почему бы не просто range.count для длины?
Лев Дабус
2

подробности

  • Swift 5.2, Xcode 11.4 (11E146)

Решение

protocol AttributedStringComponent {
    var text: String { get }
    func getAttributes() -> [NSAttributedString.Key: Any]?
}

// MARK: String extensions

extension String: AttributedStringComponent {
    var text: String { self }
    func getAttributes() -> [NSAttributedString.Key: Any]? { return nil }
}

extension String {
    func toAttributed(with attributes: [NSAttributedString.Key: Any]?) -> NSAttributedString {
        .init(string: self, attributes: attributes)
    }
}

// MARK: NSAttributedString extensions

extension NSAttributedString: AttributedStringComponent {
    var text: String { string }

    func getAttributes() -> [Key: Any]? {
        if string.isEmpty { return nil }
        var range = NSRange(location: 0, length: string.count)
        return attributes(at: 0, effectiveRange: &range)
    }
}

extension NSAttributedString {

    convenience init?(from attributedStringComponents: [AttributedStringComponent],
                      defaultAttributes: [NSAttributedString.Key: Any],
                      joinedSeparator: String = " ") {
        switch attributedStringComponents.count {
        case 0: return nil
        default:
            var joinedString = ""
            typealias SttributedStringComponentDescriptor = ([NSAttributedString.Key: Any], NSRange)
            let sttributedStringComponents = attributedStringComponents.enumerated().flatMap { (index, component) -> [SttributedStringComponentDescriptor] in
                var components = [SttributedStringComponentDescriptor]()
                if index != 0 {
                    components.append((defaultAttributes,
                                       NSRange(location: joinedString.count, length: joinedSeparator.count)))
                    joinedString += joinedSeparator
                }
                components.append((component.getAttributes() ?? defaultAttributes,
                                   NSRange(location: joinedString.count, length: component.text.count)))
                joinedString += component.text
                return components
            }

            let attributedString = NSMutableAttributedString(string: joinedString)
            sttributedStringComponents.forEach { attributedString.addAttributes($0, range: $1) }
            self.init(attributedString: attributedString)
        }
    }
}

использование

let defaultAttributes = [
    .font: UIFont.systemFont(ofSize: 16, weight: .regular),
    .foregroundColor: UIColor.blue
] as [NSAttributedString.Key : Any]

let marketingAttributes = [
    .font: UIFont.systemFont(ofSize: 20.0, weight: .bold),
    .foregroundColor: UIColor.black
] as [NSAttributedString.Key : Any]

let attributedStringComponents = [
    "pay for",
    NSAttributedString(string: "one",
                       attributes: marketingAttributes),
    "and get",
    "three!\n".toAttributed(with: marketingAttributes),
    "Only today!".toAttributed(with: [
        .font: UIFont.systemFont(ofSize: 16.0, weight: .bold),
        .foregroundColor: UIColor.red
    ])
] as [AttributedStringComponent]
let attributedText = NSAttributedString(from: attributedStringComponents, defaultAttributes: defaultAttributes)

Полный пример

не забудьте вставить код решения здесь

import UIKit

class ViewController: UIViewController {

    private weak var label: UILabel!
    override func viewDidLoad() {
        super.viewDidLoad()
        let label = UILabel(frame: .init(x: 40, y: 40, width: 300, height: 80))
        label.numberOfLines = 2
        view.addSubview(label)
        self.label = label

        let defaultAttributes = [
            .font: UIFont.systemFont(ofSize: 16, weight: .regular),
            .foregroundColor: UIColor.blue
        ] as [NSAttributedString.Key : Any]

        let marketingAttributes = [
            .font: UIFont.systemFont(ofSize: 20.0, weight: .bold),
            .foregroundColor: UIColor.black
        ] as [NSAttributedString.Key : Any]

        let attributedStringComponents = [
            "pay for",
            NSAttributedString(string: "one",
                               attributes: marketingAttributes),
            "and get",
            "three!\n".toAttributed(with: marketingAttributes),
            "Only today!".toAttributed(with: [
                .font: UIFont.systemFont(ofSize: 16.0, weight: .bold),
                .foregroundColor: UIColor.red
            ])
        ] as [AttributedStringComponent]
        label.attributedText = NSAttributedString(from: attributedStringComponents, defaultAttributes: defaultAttributes)
        label.textAlignment = .center
    }
}

результат

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

Василий Боднарчук
источник
1

Будет действительно легко решить вашу проблему с библиотекой, которую я создал. Это называется Атрибутика.

let calculatedCoffee: Int = 768
let g = Style("g").font(.boldSystemFont(ofSize: 12)).foregroundColor(.red)
let all = Style.font(.systemFont(ofSize: 12))

let str = "\(calculatedCoffee)<g>g</g>".style(tags: g)
    .styleAll(all)
    .attributedString

label.attributedText = str

768g

Вы можете найти его здесь https://github.com/psharanda/Atributika

Павел Шаранда
источник
1
 let attrString = NSAttributedString (
            string: "title-title-title",
            attributes: [NSAttributedStringKey.foregroundColor: UIColor.black])
Евгений Брагинец
источник
1

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

``` Swift
let defaultGenreText = NSAttributedString(string: "Select Genre - Required")
let redGenreText = defaultGenreText.applying(attributes: [NSAttributedString.Key.foregroundColor : UIColor.red], toRangesMatching: "Required")
``

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

Вы можете сделать это за один шаг, просто легче читать, когда разделены.

Вреж Гулян
источник
0

Swift 4.x

let attr = [NSForegroundColorAttributeName:self.configuration.settingsColor, NSFontAttributeName: self.configuration.settingsFont]

let title = NSAttributedString(string: self.configuration.settingsTitle,
                               attributes: attr)
Арунабх Дас
источник
0

Swift 3.0 // создаем приписанную строку

Определите атрибуты как

let attributes = [NSAttributedStringKey.font : UIFont.init(name: "Avenir-Medium", size: 13.0)]
iOS разработчик
источник
0

Пожалуйста, рассмотрите возможность использования Prestyler

import Prestyler
...
Prestyle.defineRule("$", UIColor.red)
label.attributedText = "\(calculatedCoffee) $g$".prestyled()
Kruiller
источник
0

Swift 5

    let attrStri = NSMutableAttributedString.init(string:"This is red")
    let nsRange = NSString(string: "This is red").range(of: "red", options: String.CompareOptions.caseInsensitive)
    attrStri.addAttributes([NSAttributedString.Key.foregroundColor : UIColor.red, NSAttributedString.Key.font: UIFont.init(name: "PTSans-Regular", size: 15.0) as Any], range: nsRange)
    self.label.attributedText = attrStri

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

Гурджиндер Сингх
источник
-4
extension String {
//MARK: Getting customized string
struct StringAttribute {
    var fontName = "HelveticaNeue-Bold"
    var fontSize: CGFloat?
    var initialIndexOftheText = 0
    var lastIndexOftheText: Int?
    var textColor: UIColor = .black
    var backGroundColor: UIColor = .clear
    var underLineStyle: NSUnderlineStyle = .styleNone
    var textShadow: TextShadow = TextShadow()

    var fontOfText: UIFont {
        if let font = UIFont(name: fontName, size: fontSize!) {
            return font
        } else {
            return UIFont(name: "HelveticaNeue-Bold", size: fontSize!)!
        }
    }

    struct TextShadow {
        var shadowBlurRadius = 0
        var shadowOffsetSize = CGSize(width: 0, height: 0)
        var shadowColor: UIColor = .clear
    }
}
func getFontifiedText(partOfTheStringNeedToConvert partTexts: [StringAttribute]) -> NSAttributedString {
    let fontChangedtext = NSMutableAttributedString(string: self, attributes: [NSFontAttributeName: UIFont(name: "HelveticaNeue-Bold", size: (partTexts.first?.fontSize)!)!])
    for eachPartText in partTexts {
        let lastIndex = eachPartText.lastIndexOftheText ?? self.count
        let attrs = [NSFontAttributeName : eachPartText.fontOfText, NSForegroundColorAttributeName: eachPartText.textColor, NSBackgroundColorAttributeName: eachPartText.backGroundColor, NSUnderlineStyleAttributeName: eachPartText.underLineStyle, NSShadowAttributeName: eachPartText.textShadow ] as [String : Any]
        let range = NSRange(location: eachPartText.initialIndexOftheText, length: lastIndex - eachPartText.initialIndexOftheText)
        fontChangedtext.addAttributes(attrs, range: range)
    }
    return fontChangedtext
}

}

// Используйте это как ниже

    let someAttributedText = "Some   Text".getFontifiedText(partOfTheStringNeedToConvert: <#T##[String.StringAttribute]#>)
Манас Мишра
источник
2
Этот ответ расскажет вам все, что вам нужно знать, кроме как сделать атрибутивную строку в быстрой.
Эрик