Come posso creare una stringa attribuita usando Swift?

Sto cercando di creare un semplice Coffee Calculator. Ho bisogno di visualizzare la quantità di caffè in grammi. Il simbolo “g” per grammi deve essere allegato alla mia UILabel che sto usando per visualizzare l’importo. I numeri nella UILabel cambiano dynamicmente con l’input dell’utente, ma ho bisogno di aggiungere una “g” minuscola alla fine della stringa che è formattata in modo diverso dai numeri di aggiornamento. La “g” deve essere allegata ai numeri in modo che quando la dimensione del numero e la posizione cambiano, la “g” “si sposta” con i numeri. Sono sicuro che questo problema è stato risolto prima, quindi un link nella giusta direzione sarebbe utile perché ho cercato su Google il mio piccolo cuore.

Ho cercato attraverso la documentazione per una stringa attribuita e ho anche fatto un downloded di “Attributed String Creator” dall’app store, ma il codice risultante è in Objective-C e sto usando Swift. Ciò che sarebbe fantastico e probabilmente utile per altri sviluppatori che imparano questo linguaggio, è un chiaro esempio di creazione di un carattere personalizzato con attributi personalizzati utilizzando una stringa attribuita in Swift. La documentazione per questo è molto confusa in quanto non vi è un percorso molto chiaro su come farlo. Il mio piano è creare la stringa attribuita e aggiungerla alla fine della mia stringa coffeeAmount.

var coffeeAmount: String = calculatedCoffee + attributedText 

Dove calcolatoCoffee è un Int convertito in una stringa e “attributeText” è la “g” minuscola con carattere personalizzato che sto cercando di creare. Forse sto andando su questo nel modo sbagliato. Qualsiasi aiuto è apprezzato!

inserisci la descrizione dell'immagine qui

Questa risposta è stata aggiornata per Swift 4.0.

Riferimento rapido

La forma generale per creare e impostare una stringa attribuita è come questa. Puoi trovare altre opzioni comuni di seguito.

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

Colore del testo

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

Colore di sfondo

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

Font

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

inserisci la descrizione dell'immagine qui

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

inserisci la descrizione dell'immagine qui

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

Il resto di questo post fornisce maggiori dettagli per coloro che sono interessati.


attributi

Gli attributi di stringa sono solo un dizionario sotto forma di [NSAttributedStringKey: Any] , dove NSAttributedStringKey è il nome chiave dell’attributo e Any è il valore di alcuni Type. Il valore potrebbe essere un font, un colore, un intero o qualcos’altro. Ci sono molti attributi standard in Swift che sono già stati predefiniti. Per esempio:

  • nome chiave: NSAttributedStringKey.font , value: a UIFont
  • nome chiave: NSAttributedStringKey.foregroundColor , value: a UIColor
  • nome chiave: NSAttributedStringKey.link , valore: un NSURL o una String

Ce ne sono molti altri Vedi questo link per saperne di più. Puoi persino creare i tuoi attributi personalizzati come:

  • nome chiave: NSAttributedStringKey.myName , value: some Type.
    se fai un’estensione :

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

Creazione di attributi in Swift

È ansible dichiarare attributi proprio come dichiarare qualsiasi altro dizionario.

 // 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" ] 

Nota il valore rawValue che era necessario per il valore dello stile di sottolineatura.

Poiché gli attributi sono solo dizionari, puoi anche crearli creando un dizionario vuoto e aggiungendo coppie di valori-chiave. Se il valore conterrà più tipi, dovrai utilizzare Any come tipo. Ecco l’esempio multipleAttributes di cui sopra, ricreato in questo modo:

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

Archi attribuiti

Ora che comprendi gli attributi, puoi creare stringhe attribuite.

Inizializzazione

Esistono alcuni modi per creare stringhe attribuite. Se hai solo bisogno di una stringa di sola lettura, puoi utilizzare NSAttributedString . Ecco alcuni modi per inizializzarlo:

 // 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 è necessario modificare gli attributi o il contenuto della stringa in un secondo momento, è necessario utilizzare NSMutableAttributedString . Le dichiarazioni sono molto simili:

 // 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) 

Modifica di una stringa attribuita

Ad esempio, creiamo la stringa attribuita nella parte superiore di questo post.

Crea innanzitutto un NSMutableAttributedString con un nuovo attributo font.

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

Se stai lavorando, imposta la stringa attribuita a UITextView (o UILabel ) in questo modo:

 textView.attributedText = myString 

Non usi textView.text .

Ecco il risultato:

inserisci la descrizione dell'immagine qui

Quindi aggiungi un’altra stringa attribuita che non ha alcun attributo impostato. (Si noti che anche se ho usato let dichiarare myString sopra, posso ancora modificarlo perché è un NSMutableAttributedString sembra piuttosto unSwiftlike per me e non sarei sorpreso se questo cambia in futuro. accade.)

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

inserisci la descrizione dell'immagine qui

Quindi selezioneremo la parola “Strings”, che inizia dall’indice 17 e ha una lunghezza di 7 . Si noti che questo è un NSRange e non un Swift Range . (Vedere questa risposta per ulteriori informazioni sugli intervalli.) Il metodo addAttribute ci consente di inserire il nome della chiave dell’attributo nel primo punto, il valore dell’attributo nel secondo punto e l’intervallo nel terzo punto.

 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) 

inserisci la descrizione dell'immagine qui

Infine, aggiungiamo un colore di sfondo. Per varietà, usiamo il metodo addAttributes (notare la s ). Potrei aggiungere più attributi contemporaneamente con questo metodo, ma ne aggiungerò uno nuovo.

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

inserisci la descrizione dell'immagine qui

Si noti che gli attributi si sovrappongono in alcuni punti. L’aggiunta di un attributo non sovrascrive un attributo già presente.

Relazionato

  • Come modificare il testo di NSMutableAttributedString ma mantenere gli attributi

Ulteriori letture

  • Come recuperare gli attributi da una posizione di touch
  • Guida alla programmazione delle stringhe attribuita (molto informativa ma sfortunatamente solo in Objective-C)

Swift usa la stessa NSMutableAttributedString che fa Obj-C. Puoi istanziarlo passando il valore calcolato come una stringa:

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

Ora crea la stringa g attribuita (heh). Nota: UIFont.systemFontOfSize(_) è ora un inizializzatore disponibile, pertanto deve essere rimosso prima di poterlo utilizzare:

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

E poi aggiungilo:

 attributedString.appendAttributedString(gString) 

È quindi ansible impostare UILabel per visualizzare NSAttributededtring in questo modo:

 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] 

Versione Xcode 6 :

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

Versione Xcode 9.3 :

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

Consiglio vivamente l’uso di una libreria per le stringhe attribuite. Rende molto più semplice quando si desidera, ad esempio, una stringa con quattro colors diversi e quattro tipi di carattere diversi. Ecco il mio preferito. Si chiama SwiftyAttributes

Se si desidera creare una stringa con quattro colors diversi e caratteri diversi 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 mostrerebbe come

Mostra come immagine

Funziona bene nella beta 6

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

Swift 2.0

Ecco un esempio:

 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 

O

 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 

Ho creato uno strumento online che risolverà il tuo problema! Puoi scrivere la tua stringa e applicare gli stili graficamente e lo strumento ti fornisce codice ogg-c e swift per generare quella stringa.

Inoltre è open source quindi sentitevi liberi di estenderlo e inviare PR.

Strumento di trasformazione

Github

inserisci la descrizione dell'immagine qui

 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 } 

//Implementazione

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

Per me sopra le soluzioni non ha funzionato quando si imposta un colore o una proprietà specifici.

Questo ha funzionato:

 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 

Il modo migliore per approcciare le stringhe attribuite su iOS consiste nell’utilizzare l’editor di testo attribuito integrato nel builder dell’interfaccia ed evitare la codifica non necessaria NSAtrributedStringKeys nei file di origine.

In seguito puoi sostituire dynamicmente placehoderls in fase di esecuzione utilizzando questa estensione:

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

Aggiungi un’etichetta storyboard con testo attribuito simile a questo.

inserisci la descrizione dell'immagine qui

Quindi devi semplicemente aggiornare il valore ogni volta che ti serve in questo modo:

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

Assicurati di salvare initalAttributoStringa il valore originale.

Puoi capire meglio questo approccio leggendo questo articolo: https://medium.com/mobile-appetite/text-attributes-on-ios-the-effortless-approach-ff086588173e

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) 

Devi rimuovere il valore raw in 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]) 

Sarà davvero facile risolvere il tuo problema con la libreria che ho creato. Si chiama 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

Potete trovarlo qui https://github.com/psharanda/Atributika

Gli attributi possono essere impostati direttamente in swift 3 …

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

Quindi utilizza la variabile in qualsiasi class con attributi

 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 } 

}

// Usalo come sotto

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