Como eu faço uma string atribuída usando o Swift?

Eu estou tentando fazer uma simples calculadora de café. Eu preciso mostrar a quantidade de café em gramas. O símbolo “g” para gramas precisa ser anexado ao meu UILabel que estou usando para exibir o valor. Os números no UILabel estão mudando dinamicamente com a input do usuário muito bem, mas eu preciso adicionar um minúsculo “g” no final da string que é formatado de forma diferente dos números de atualização. O “g” precisa ser anexado aos números para que, à medida que o tamanho e a posição do número mudem, o “g” “se mova” com os números. Tenho certeza de que esse problema foi resolvido antes, de modo que um link na direção certa seria útil, pois eu pesquisei meu pequeno coração no google.

Eu procurei na documentação por uma string atribuída e eu até mesmo fiz downgrade de um “Attributed String Creator” da loja de aplicativos, mas o código resultante está em Objective-C e estou usando o Swift. O que seria incrível e provavelmente útil para outros desenvolvedores que estão aprendendo essa linguagem, é um exemplo claro de criação de uma fonte personalizada com atributos personalizados usando uma string atribuída no Swift. A documentação para isso é muito confusa, pois não há um caminho muito claro sobre como fazê-lo. Meu plano é criar a string atribuída e adicioná-la ao final da minha string coffeeAmount.

var coffeeAmount: String = calculatedCoffee + attributedText 

Onde calculateCoffee é um Int convertido em uma string e “assignedText” é o “g” minúsculo com fonte personalizada que estou tentando criar. Talvez eu esteja indo sobre o caminho errado. Qualquer ajuda é apreciada!

insira a descrição da imagem aqui

Essa resposta foi atualizada para o Swift 4.0.

Referência rápida

A forma geral de criar e definir uma string atribuída é assim. Você pode encontrar outras opções comuns abaixo.

 // create attributed string let myString = "Swift Attributed String" let myAttribute = [ NSAttributedStringKey.foregroundColor: UIColor.blue ] let myAttrString = NSAttributedString(string: myString, attributes: myAttribute) // set attributed text on a UILabel myLabel.attributedText = myAttrString 

Cor do texto

 let myAttribute = [ NSAttributedStringKey.foregroundColor: UIColor.blue ] 

Cor de fundo

 let myAttribute = [ NSAttributedStringKey.backgroundColor: UIColor.yellow ] 

Fonte

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

insira a descrição da imagem aqui

 let myAttribute = [ NSAttributedStringKey.underlineStyle: NSUnderlineStyle.styleSingle.rawValue ] 

insira a descrição da imagem aqui

 let myShadow = NSShadow() myShadow.shadowBlurRadius = 3 myShadow.shadowOffset = CGSize(width: 3, height: 3) myShadow.shadowColor = UIColor.gray let myAttribute = [ NSAttributedStringKey.shadow: myShadow ] 

O resto deste post dá mais detalhes para aqueles que estão interessados.


Atributos

Atributos de cadeia de caracteres são apenas um dictionary na forma de [NSAttributedStringKey: Any] , onde NSAttributedStringKey é o nome da chave do atributo e Any é o valor de algum Type. O valor pode ser uma fonte, uma cor, um inteiro ou outra coisa. Existem muitos atributos padrão no Swift que já foram predefinidos. Por exemplo:

  • nome da chave: NSAttributedStringKey.font , value: a UIFont
  • nome da chave: NSAttributedStringKey.foregroundColor , value: a UIColor
  • nome da chave: NSAttributedStringKey.link , value: an NSURL ou String

Existem muitos outros. Veja este link para mais. Você pode até criar seus próprios atributos personalizados como:

  • nome da chave: NSAttributedStringKey.myName , value: some Type.
    se você fizer uma extensão :

     extension NSAttributedStringKey { static let myName = NSAttributedStringKey(rawValue: "myCustomAttributeKey") } 

Criando atributos no Swift

Você pode declarar atributos como declarar qualquer outro dictionary.

 // single attributes declared one at a time let singleAttribute1 = [ NSAttributedStringKey.foregroundColor: UIColor.green ] let singleAttribute2 = [ NSAttributedStringKey.backgroundColor: UIColor.yellow ] let singleAttribute3 = [ NSAttributedStringKey.underlineStyle: NSUnderlineStyle.styleDouble.rawValue ] // multiple attributes declared at once let multipleAttributes: [NSAttributedStringKey : Any] = [ NSAttributedStringKey.foregroundColor: UIColor.green, NSAttributedStringKey.backgroundColor: UIColor.yellow, NSAttributedStringKey.underlineStyle: NSUnderlineStyle.styleDouble.rawValue ] // custom attribute let customAttribute = [ NSAttributedStringKey.myName: "Some value" ] 

Observe o rawValue que era necessário para o valor de estilo de sublinhado.

Como os atributos são apenas Dicionários, você também pode criá-los, criando um Dicionário vazio e adicionando pares de valores-chave a ele. Se o valor contiver vários tipos, você deverá usar Any como o tipo. Aqui está o exemplo multipleAttributes de cima, recriado desta maneira:

 var multipleAttributes = [NSAttributedStringKey : Any]() multipleAttributes[NSAttributedStringKey.foregroundColor] = UIColor.green multipleAttributes[NSAttributedStringKey.backgroundColor] = UIColor.yellow multipleAttributes[NSAttributedStringKey.underlineStyle] = NSUnderlineStyle.styleDouble.rawValue 

Strings Atribuídas

Agora que você entende os atributos, pode criar strings atribuídas.

Inicialização

Existem algumas maneiras de criar strings atribuídas. Se você precisar apenas de uma string somente leitura, poderá usar NSAttributedString . Aqui estão algumas maneiras de inicializá-lo:

 // Initialize with a string only let attrString1 = NSAttributedString(string: "Hello.") // Initialize with a string and inline attribute(s) let attrString2 = NSAttributedString(string: "Hello.", attributes: [NSAttributedStringKey.myName: "A value"]) // Initialize with a string and separately declared attribute(s) let myAttributes1 = [ NSAttributedStringKey.foregroundColor: UIColor.green ] let attrString3 = NSAttributedString(string: "Hello.", attributes: myAttributes1) 

Se você precisar alterar os atributos ou o conteúdo da cadeia posteriormente, deverá usar NSMutableAttributedString . As declarações são muito semelhantes:

 // 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: [NSAttributedStringKey.myName: "A value"]) // Initialize with a string and separately declared attribute(s) let myAttributes2 = [ NSAttributedStringKey.foregroundColor: UIColor.green ] let mutableAttrString4 = NSMutableAttributedString(string: "Hello.", attributes: myAttributes2) 

Alterando uma String Atribuída

Como exemplo, vamos criar a string atribuída no topo desta postagem.

Primeiro, crie um NSMutableAttributedString com um novo atributo de fonte.

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

Se você estiver trabalhando, configure a string atribuída para um UITextView (ou UILabel ) assim:

 textView.attributedText = myString 

Você não usa textView.text .

Aqui está o resultado:

insira a descrição da imagem aqui

Em seguida, anexe outra sequência atribuída que não tenha nenhum conjunto de atributos. (Observe que, embora eu tenha usado let para declarar myString acima, eu ainda posso modificá-lo porque é um NSMutableAttributedString . Isso parece bastante improvável para mim e eu não ficaria surpreso se isso mudasse no futuro. Deixe-me um comentário quando acontece.)

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

insira a descrição da imagem aqui

Em seguida, basta selecionar a palavra “Strings”, que começa no índice 17 e tem um comprimento de 7 . Observe que este é um NSRange e não um Swift Range . (Veja esta resposta para mais informações sobre Ranges.) O método addAttribute nos permite colocar o nome da chave de atributo no primeiro ponto, o valor do atributo no segundo ponto e o intervalo no terceiro ponto.

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

insira a descrição da imagem aqui

Finalmente, vamos adicionar uma cor de fundo. Para addAttributes , vamos usar o método addAttributes (observe os s ). Eu poderia adicionar vários atributos de uma só vez com este método, mas apenas adicionarei um novamente.

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

insira a descrição da imagem aqui

Observe que os atributos estão sobrepostos em alguns lugares. Adicionar um atributo não sobrescreve um atributo que já está lá.

Relacionado

  • Como alterar o texto de um NSMutableAttributedString mas manter os atributos

Leitura Adicional

  • Como recuperar os atributos de um local de toque
  • Guia de Programação de String Atribuída (muito informativo, mas infelizmente apenas em Objective-C)

O Swift usa o mesmo NSMutableAttributedString que o Obj-C faz. Você instancia isso passando o valor calculado como uma string:

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

Agora crie a string g atribuída (heh). Nota: UIFont.systemFontOfSize(_) agora é um inicializador de segurança, portanto, ele precisa ser desembrulhado antes de você poder usá-lo:

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

E, em seguida, anexe-o:

 attributedString.appendAttributedString(gString) 

Em seguida, você pode definir o UILabel para exibir o NSAttributedString da seguinte maneira:

 myLabel.attributedText = attributedString 

Swift: xcode 6.1

  let font:UIFont? = UIFont(name: "Arial", size: 12.0) let attrString = NSAttributedString( string: titleData, attributes: NSDictionary( object: font!, forKey: NSFontAttributeName)) 

Swift 4:

 let attributes = [NSAttributedStringKey.font: UIFont(name: "HelveticaNeue-Bold", size: 17)!, NSAttributedStringKey.foregroundColor: UIColor.white] 

Versão do Xcode 6 :

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

Versão do Xcode 9.3 :

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

Eu recomendaria altamente usar uma biblioteca para cadeias atribuídas. Isso facilita muito quando você deseja, por exemplo, uma seqüência de caracteres com quatro colors diferentes e quatro fonts diferentes. Aqui é o meu favorito. Chama-se SwiftyAttributes

Se você quisesse criar uma string com quatro colors diferentes e fonts diferentes usando 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 mostraria como

Mostra como imagem

Funciona bem no beta 6

 let attrString = NSAttributedString( string: "title-title-title", attributes: NSDictionary( object: NSFont(name: "Arial", size: 12.0), forKey: NSFontAttributeName)) 

Swift 2.0

Aqui está uma amostra:

 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 

OU

 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 

Eu criei uma ferramenta online que vai resolver o seu problema! Você pode escrever sua string e aplicar estilos graficamente, e a ferramenta lhe dá um código object-c e swift para gerar essa string.

Também é open source então fique à vontade para estendê-lo e enviar PRs.

Ferramenta Transformadora

Github

insira a descrição da imagem aqui

Para mim, as soluções acima não funcionaram quando definimos uma cor ou propriedade específica.

Isso funcionou:

 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) 

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 

A melhor maneira de abordar Strings Atribuídas no iOS é usar o editor de Texto Atributo integrado no construtor de interface e evitar a codificação não desejada NSAtrributedStringKeys em seus arquivos de origem.

Mais tarde você pode dinamicamente replace placehoderls em tempo de execução usando esta extensão:

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

Adicione um marcador de storyboard com o texto atribuído com esta aparência.

insira a descrição da imagem aqui

Então você simplesmente atualiza o valor toda vez que você precisa assim:

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

Certifique-se de salvar em initalAttributedString o valor original.

Você pode entender melhor essa abordagem lendo este artigo: https://medium.com/mobile-appetite/text-attributes-on-ios-the-effortless-approach-ff086588173e

 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 } 

//Implementação

 cell.lblFrom.attributedText = decorateText(sub: sender!, des: " - \(convertDateFormatShort3(myDateString: datetime!))") 

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) 

Você precisa remover o valor bruto em swift 4

 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 } } 
  let attrString = NSAttributedString ( string: "title-title-title", attributes: [NSAttributedStringKey.foregroundColor: UIColor.black]) 

Será muito fácil resolver seu problema com a biblioteca que criei. É chamado 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".style(tags: g) .styleAll(all) .attributedString label.attributedText = str 

768g

Você pode encontrá-lo aqui https://github.com/psharanda/Atributika

Os atributos podem ser definidos diretamente em swift 3 …

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

Em seguida, use a variável em qualquer class com atributos

 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 } 

}

// Use como abaixo

  let someAttributedText = "Some Text".getFontifiedText(partOfTheStringNeedToConvert: < #T##[String.StringAttribute]#>)