Как создать привязанную строку с помощью Swift?
Я пытаюсь сделать простой калькулятор кофе. Мне нужно отображать количество кофе в граммах. Символ "g" для граммов должен быть прикреплен к моей UILabel, который я использую для отображения суммы. Цифры в UILabel динамически меняются при вводе пользователя очень хорошо, но мне нужно добавить нижний регистр "g" в конце строки, которая отформатирована иначе, чем номера обновлений. "G" необходимо привязать к номерам, чтобы при изменении размера и позиции числа "g" "перемещается" с номерами. Я уверен, что эта проблема была решена до того, как бы ссылка в правильном направлении была бы полезна, поскольку я искал свое маленькое сердце.
Я просмотрел документацию для присваиваемой строки, и я даже уменьшил "Attributed String Creator" из магазина приложений, но полученный код находится в Objective-C, и я использую Swift. Что было бы удивительным и, вероятно, полезным для других разработчиков, изучающих этот язык, является ярким примером создания настраиваемого шрифта с пользовательскими атрибутами с использованием атрибутной строки в Swift. Документация для этого очень запутанна, так как нет четкого пути к тому, как это сделать. Мой план состоит в том, чтобы создать атрибутную строку и добавить ее в конец моей строки coffeeAmount.
var coffeeAmount: String = calculatedCoffee + attributedText
Где calculateCoffee - Int, преобразованный в строку, и "attributedText" - это строчный "g" с настраиваемым шрифтом, который я пытаюсь создать. Возможно, я ошибаюсь. Любая помощь приветствуется!
Ответы
Ответ 1
![enter image description here]()
Этот ответ был обновлен для 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
![Text Color]()
let myAttribute = [ NSAttributedString.Key.foregroundColor: UIColor.blue ]
![Background Color]()
let myAttribute = [ NSAttributedString.Key.backgroundColor: UIColor.yellow ]
![Font]()
let myAttribute = [ NSAttributedString.Key.font: UIFont(name: "Chalkduster", size: 18.0)! ]
![enter image description here]()
let myAttribute = [ NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue ]
![enter image description here]()
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
, значение: UIFont
- имя ключа:
NSAttributedString.Key.foregroundColor
, значение: UIColor
- имя ключа:
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
атрибутивную строку UITextView
(или UILabel
) следующим образом:
textView.attributedText = myString
Вы не используете textView.text
.
Вот результат:
![enter image description here]()
Затем добавьте еще одну атрибутивную строку, для которой не установлены никакие атрибуты. (Обратите внимание, что хотя я и использовал let
для объявления myString
выше, я все же могу изменить его, потому что это NSMutableAttributedString
. NSMutableAttributedString
это кажется довольно непривлекательным, и я не удивлюсь, если это изменится в будущем. Оставьте мне комментарий, когда это случается.)
let attrString = NSAttributedString(string: " Attributed Strings")
myString.append(attrString)
![enter image description here]()
Далее мы просто выберем слово "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)
![enter image description here]()
Наконец, позвольте добавить цвет фона. Для разнообразия, давайте использовать addAttributes
метод (обратите внимание на s
). Я мог бы добавить несколько атрибутов одновременно с этим методом, но я просто добавлю один снова.
myRange = NSRange(location: 3, length: 17)
let anotherAttribute = [ NSAttributedString.Key.backgroundColor: UIColor.yellow ]
myString.addAttributes(anotherAttribute, range: myRange)
![enter image description here]()
Обратите внимание, что атрибуты перекрываются в некоторых местах. Добавление атрибута не перезаписывает атрибут, который уже существует.
связанные с
Дальнейшее чтение
Ответ 2
Swift использует тот же NSMutableAttributedString
, что и Obj-C. Вы создаете экземпляр, передавая в вычисленном значении строку:
var attributedString = NSMutableAttributedString(string:"\(calculatedCoffee)")
Теперь создайте атрибут g
string (heh). Примечание. UIFont.systemFontOfSize(_)
теперь является отказоустойчивым инициализатором, поэтому его необходимо развернуть, прежде чем вы сможете его использовать:
var attrs = [NSFontAttributeName : UIFont.systemFontOfSize(19.0)!]
var gString = NSMutableAttributedString(string:"g", attributes:attrs)
И затем добавьте его:
attributedString.appendAttributedString(gString)
Затем вы можете установить UILabel для отображения NSAttributedString следующим образом:
myLabel.attributedText = attributedString
Ответ 3
Swift 4:
let attributes = [NSAttributedStringKey.font: UIFont(name: "HelveticaNeue-Bold", size: 17)!,
NSAttributedStringKey.foregroundColor: UIColor.white]
Ответ 4
Версия 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])
Ответ 5
Swift: xcode 6.1
let font:UIFont? = UIFont(name: "Arial", size: 12.0)
let attrString = NSAttributedString(
string: titleData,
attributes: NSDictionary(
object: font!,
forKey: NSFontAttributeName))
Ответ 6
Я бы очень рекомендовал использовать библиотеку для атрибутных строк. Это делает его намного проще, если вы хотите, например, одну строку с четырьмя разными цветами и четырьмя разными шрифтами. Вот мой любимый. Он называется 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
будет отображаться как
![Показывает как изображение]()
Ответ 7
Хорошо работает в бета-версии 6
let attrString = NSAttributedString(
string: "title-title-title",
attributes: NSDictionary(
object: NSFont(name: "Arial", size: 12.0),
forKey: NSFontAttributeName))
Ответ 8
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
ИЛИ
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
Ответ 9
Я создал онлайн-инструмент, который решит вашу проблему! Вы можете написать свою строку и применить стили в графическом виде, и инструмент предоставит вам код target-c и swift для генерации этой строки.
Также с открытым исходным кодом, так что не стесняйтесь расширять его и отправлять PR.
Инструмент Трансформер
Github
![enter image description here]()
Ответ 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
}
}
Добавьте метку раскадровки с атрибутивным текстом, который выглядит следующим образом.
![enter image description here]()
Затем вы просто обновляете значение каждый раз, когда вам это нужно:
label.attributedText = initalAttributedString.replacing(placeholder: "<price>", with: newValue)
Обязательно сохраните в initalAttributedString исходное значение.
Вы можете лучше понять этот подход, прочитав эту статью: https://medium.com/mobile-appetite/text-attributes-on-ios-the-effortless-approach-ff086588173e
Ответ 11
Для меня выше решения не срабатывали при настройке определенного цвета или свойства.
Это работало:
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)
Ответ 12
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!))")
Ответ 13
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
Ответ 14
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
Ответ 15
let attrString = NSAttributedString (
string: "title-title-title",
attributes: [NSAttributedStringKey.foregroundColor: UIColor.black])
Ответ 16
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
}
}
Ответ 17
Атрибуты могут устанавливаться непосредственно в swift 3...
let attributes = NSAttributedString(string: "String", attributes: [NSFontAttributeName : UIFont(name: "AvenirNext-Medium", size: 30)!,
NSForegroundColorAttributeName : UIColor .white,
NSTextEffectAttributeName : NSTextEffectLetterpressStyle])
Затем используйте переменную в любом классе с атрибутами
Ответ 18
Будет очень легко решить вашу проблему с созданной мной библиотекой. Он называется Atributika.
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
Ответ 19
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
}
}
Ответ 20
Swift 4.x
let attr = [NSForegroundColorAttributeName:self.configuration.settingsColor, NSFontAttributeName: self.configuration.settingsFont]
let title = NSAttributedString(string: self.configuration.settingsTitle,
attributes: attr)
Ответ 21
Swift 3.0//создаем приписанную строку
Определите атрибуты как
let attributes = [NSAttributedStringKey.font : UIFont.init(name: "Avenir-Medium", size: 13.0)]
Ответ 22
Пожалуйста, рассмотрите возможность использования Prestyler
import Prestyler
...
Prestyle.defineRule("$", UIColor.red)
label.attributedText = "\(calculatedCoffee) $g$".prestyled()
Ответ 23
Swift 5 и выше
let attributedString = NSAttributedString(string:"targetString",
attributes:[NSAttributedString.Key.foregroundColor: UIColor.lightGray,
NSAttributedString.Key.font: UIFont(name: "Arial", size: 18.0) as Any])
Ответ 24
Swifter Swift предлагает довольно приятный способ сделать это безо всякой работы. Просто предоставьте шаблон, который должен соответствовать, и какие атрибуты применить к нему. Они отлично подходят для многих вещей, проверьте их.
''' Swift
let defaultGenreText = NSAttributedString(string: "Select Genre - Required")
let redGenreText = defaultGenreText.applying(attributes: [NSAttributedString.Key.foregroundColor : UIColor.red], toRangesMatching: "Required")
''
Если у вас есть несколько мест, где это будет применяться, и вы хотите, чтобы это происходило только в определенных случаях, этот метод не сработает.
Вы можете сделать это за один шаг, просто легче читать, когда разделены.
Ответ 25
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]#>)