Tengo una cadena, digamos "mi nombre es %@ y estudio en la clase %@", ahora quiero poner en negrita el texto del marcador de posición que insertaré, para que el resultado se vea así: "Mi nombre es Harsh y estudio en la clase 10 " y lo mostraré en una etiqueta
Ya intenté usar NSAttributedString, pero dado que la cadena se localizará, no puedo usar el parámetro de rango de la cadena atribuida para ponerla en negrita.
let descriptionString = String(format: "localised_key".localized(), Harsh, 10) let description = NSMutableAttributedString(string: descriptionString, attributes: [NSAttributedString.Key.font: UIFont(name: "NotoSans-Regular", size: 15.7)!, NSAttributedString.Key.foregroundColor: UIColor(rgb: 0x000b38), NSAttributedString.Key.kern: 0.5]) let rangeName = descriptionString.range(of: "Harsh") let rangeClass = descriptionString.range(of: "10") let nsrangeName = NSRange(rangeName!, in: descriptionString) let nsrangeClass = NSRange(rangeClass!, in: descriptionString) description.addAttributes([NSAttributedString.Key.font: UIFont(name: "NotoSans-Bold", size: 15.7)!, NSAttributedString.Key.foregroundColor: UIColor(rgb: 0x000b38), NSAttributedString.Key.kern: 0.5], range: nsrangeName) description.addAttributes([NSAttributedString.Key.font: UIFont(name: "NotoSans-Bold", size: 15.7)!, NSAttributedString.Key.foregroundColor: UIColor(rgb: 0x000b38), NSAttributedString.Key.kern: 0.5], range: nsrangeClass)para más referencias, use este
let withFormat = "my name is %@ and i study in class %@"Hay diferentes formas de hacerlo, pero en mi opinión, una de las más fáciles sería usar etiquetas:
Use etiquetas alrededor de los marcadores de posición (y otras partes si es necesario):
let withFormat = "my name is <b>%@</b> and i study in class <b>%@</b>" let withFormat = "my name is [b]%@[/b] and i study in class [b]%@[/b]" let withFormat = "my name is **%@** and i study in class **%@**"Las etiquetas pueden ser HTML, Markdown, BBCode o cualquier otra personalizada que desee, luego, reemplace los valores de marcador de posición:
let localized = String(format: withFormat, value1, value2) Ahora, dependiendo de cómo quieras hacerlo, o qué etiqueta usaste, puedes usar el inicio de NSAttributedString desde HTML, Markdown, etc., o simplemente usando NSAttributedString(string: localized) , busca las etiquetas y aplica el render efecto necesario.
Aquí hay un pequeño ejemplo:
let tv = UITextView(frame: CGRect(x: 0, y: 0, width: 300, height: 130)) tv.backgroundColor = .orange let attributedString = NSMutableAttributedString() let htmled = String(format: "my name is <b>%@</b> and i study in class <b>%@</b>", arguments: ["Alice", "Wonderlands"]) let markdowned = String(format: "my name is **%@** and i study in class **%@**", arguments: ["Alice", "Wonderlands"]) let bbcoded = String(format: "my name is [b]%@[/b] and i study in class [b]%@[/b]", arguments: ["Alice", "Wonderlands"]) let separator = NSAttributedString(string: "\n\n") let html = try! NSAttributedString(data: Data(htmled.utf8), options: [.documentType : NSAttributedString.DocumentType.html], documentAttributes: nil) attributedString.append(html) attributedString.append(separator) let markdown = try! NSAttributedString(markdown: markdowned, baseURL: nil) //iO15+ attributedString.append(markdown) attributedString.append(separator) let bbcode = NSMutableAttributedString(string: bbcoded) let regex = try! NSRegularExpression(pattern: "\\[b\\](.*?)\\[\\/b\\]", options: []) let matches = regex.matches(in: bbcode.string, options: [], range: NSRange(location: 0, length: bbcode.length)) let boldEffect: [NSAttributedString.Key: Any] = [.font: UIFont.boldSystemFont(ofSize: 12)] //We use reversed() because if you replace the first one, you'll remove [b] and [/b], meaning that the other ranges will be affected, so the trick is to start from the end matches.reversed().forEach { aMatch in let valueRange = aMatch.range(at: 1) //We use the regex group let replacement = NSAttributedString(string: bbcode.attributedSubstring(from: valueRange).string, attributes: boldEffect) bbcode.replaceCharacters(in: aMatch.range, with: replacement) } attributedString.append(bbcode) tv.attributedText = attributedStringProducción: