NSAttributedString es una clase del framework Foundation en el SDK de iOS que representa una cadena con un conjunto de atributos de formato aplicados a caracteres individuales o rangos de texto. A diferencia de NSString normal, NSAttributedString almacena no solo caracteres Unicode sino también un diccionario de atributos (fuente, color, kerning, alineación) para cada segmento de la cadena. Según la Documentación para Desarrolladores de Apple (2026), NSAttributedString es la base para mostrar texto formateado en todos los componentes de UI de iOS.
Puntos clave
NSAttributedString es una clase fundamental de iOS/macOS para trabajar con texto formateado. Extiende NSString añadiendo atributos a la cadena — un diccionario de pares clave-valor donde la clave es una constante NSAttributedStringKey (por ejemplo, .font, .foregroundColor) y el valor es el objeto correspondiente (UIFont, UIColor). Cada carácter en la cadena puede tener su propio conjunto de atributos, permitiendo formato mixto dentro de una sola cadena.
La arquitectura de NSAttributedString se basa en el concepto de ejecuciones de atributos (attribute runs). Si se define el atributo .font como UIFont.boldSystemFont(ofSize: 16) para el rango de caracteres 0..5, todos los caracteres de ese rango se mostrarán en negrita. Otros caracteres pueden tener una fuente diferente o ningún atributo. Al renderizar una cadena con atributos, el sistema UIKit combina las características de diferentes rangos y renderiza el texto de manera uniforme.
NSAttributedString es inmutable — después de su creación, sus atributos y contenido no pueden modificarse. Para la modificación existe la subclase NSMutableAttributedString, que proporciona métodos para añadir, eliminar y cambiar atributos en cualquier rango. Esta distinción es importante para la concurrencia: el NSAttributedString inmutable es seguro para hilos, mientras que NSMutableAttributedString no lo es.
NSAttributedString soporta alrededor de 40 atributos estándar definidos en NSAttributedStringKey. Cada atributo afecta un aspecto específico de la apariencia del texto: fuente, color, posición, subrayado, sombra, kerning, estilo de párrafo e hipervínculos. Para definir un atributo, se usa una constante NSAttributedStringKey y se le asigna un objeto del tipo correspondiente.
| Clave de atributo | Tipo de valor | Propósito |
|---|---|---|
| .font | UIFont | Fuente y tamaño del texto |
| .foregroundColor | UIColor | Color del texto |
| .backgroundColor | UIColor | Color de fondo detrás del texto |
| .paragraphStyle | NSParagraphStyle | Alineación, interlineado, sangrías |
| .kern | NSNumber (Float) | Espaciado entre caracteres (kerning) |
| .underlineStyle | NSUnderlineStyle (Int) | Estilo de subrayado (simple, doble, grueso, patrón) |
| .strikethroughStyle | NSUnderlineStyle (Int) | Estilo de tachado |
| .link | NSURL | URL para hipervínculo interactivo |
| .shadow | NSShadow | Sombra del texto con offset, blurRadius y color |
| .baselineOffset | NSNumber (Float) | Desplazamiento del texto respecto a la línea base |
NSMutableParagraphStyle es un objeto que gestiona las características visuales de un párrafo: alineación (.alignment: .left, .center, .right, .justified), interlineado (.lineSpacing), espacio entre párrafos (.paragraphSpacing), sangría de primera línea (.firstLineHeadIndent), sangría izquierda y derecha (.headIndent, .tailIndent) y dirección del texto (.baseWritingDirection). ParagraphStyle se aplica a un rango que incluya caracteres de nueva línea si se requiere el mismo formato para todo el párrafo.
La creación de un NSAttributedString se realiza mediante un inicializador que recibe una cadena y un diccionario de atributos. Los atributos se aplican a toda la cadena. Para formato mixto (diferentes atributos en distintas partes de la cadena) se utiliza NSMutableAttributedString con la posterior adición de atributos a rangos específicos. Objective-C usa un diccionario NSAttributedStringKey: UIFont, mientras que Swift usa un diccionario [NSAttributedString.Key: Any] con seguridad de tipos.
let plainText = "Hello, Swift!"
// Create with uniform attributes for the entire string
let attributes: [NSAttributedString.Key: Any] = [
NSAttributedString.Key.font:
UIFont.systemFont(ofSize: 18),
NSAttributedString.Key.foregroundColor:
UIColor.darkText,
NSAttributedString.Key.kern: 1.5
]
let attributedString =
NSAttributedString(string: plainText,
attributes: attributes)
Un ejemplo demuestra el formato de párrafo mediante NSMutableParagraphStyle. Se establece alineación centrada, interlineado de 8 puntos, espacio después del párrafo de 12 puntos. ParagraphStyle se añade al diccionario de atributos bajo la clave .paragraphStyle. NSAttributedString copia el paragraphStyle pasado, por lo que después de crear la cadena se puede modificar sin afectar a la cadena ya creada.
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = NSTextAlignment.center
paragraphStyle.lineSpacing = 8.0
paragraphStyle.paragraphSpacing = 12.0
paragraphStyle.firstLineHeadIndent = 20.0
let attributed = NSAttributedString(
string: "Centered paragraph with spacing",
attributes: [NSAttributedString.Key.paragraphStyle: paragraphStyle])
NSMutableAttributedString es una subclase de NSAttributedString que permite modificar el contenido y los atributos después de la creación. Métodos principales: addAttribute(_:value:range:) para añadir un solo atributo a un rango; addAttributes(_:range:) para añadir múltiples atributos; setAttributes(_:range:) para reemplazar todos los atributos en un rango; removeAttribute(_:range:) para eliminar un atributo; replaceCharacters(in:with:) para reemplazar texto.
addAttribute y addAttributes añaden atributos a los existentes sin eliminar los ya establecidos. Si un rango ya tiene un atributo con la misma clave, su valor se reemplaza. setAttributes reemplaza completamente el diccionario de atributos para un rango — todos los atributos previamente establecidos se eliminan. Esto es importante de entender al formatear secuencialmente una sola cadena: addAttributes es más seguro ya que no restablece las fuentes y colores ya configurados.
Los rangos (NSRange) se especifican mediante la estructura NSRange(location: 0, length: 5). location es el índice inicial (basado en 0), length es el número de caracteres. Si el rango excede los límites de la cadena, NSMutableAttributedString lanza una excepción NSRangeException. Para operaciones seguras con rangos, se usan métodos NSRange de Foundation como NSIntersectionRange y NSUnionRange.
let attributed = NSMutableAttributedString(
string: "Bold and red text here")
// Apply bold font to first 9 characters
let boldRange = NSRange(location: 0, length: 9)
attributed.addAttribute(
NSAttributedString.Key.font,
value: UIFont.boldSystemFont(ofSize: 16),
range: boldRange)
// Apply red color to characters 13-16 ("text")
let redRange = NSRange(location: 13, length: 4)
attributed.addAttribute(
NSAttributedString.Key.foregroundColor,
value: UIColor.red,
range: redRange)
// Apply underline to the entire string
let fullRange = NSRange(location: 0,
length: attributed.length)
attributed.addAttribute(
NSAttributedString.Key.underlineStyle,
value: NSUnderlineStyle.single.rawValue,
range: fullRange)
La forma más común de mostrar un NSAttributedString es asignarlo a la propiedad attributedText de un UILabel. A diferencia de la propiedad text, attributedText usa los atributos para el renderizado, soportando formato mixto. Importante: si se define attributedText, UILabel ignora las propiedades font, textColor y textAlignment — todas las características visuales se toman de los atributos de NSAttributedString.
let label = UILabel()
label.numberOfLines = 0
let fullText = NSMutableAttributedString(
string: "Price: $24.99 per month")
// Format "Price:" label with bold font
let priceLabelRange = NSRange(
location: 0, length: 6)
fullText.addAttribute(
NSAttributedString.Key.font,
value: UIFont.boldSystemFont(ofSize: 16),
range: priceLabelRange)
// Format "$24.99" with green color
let amountRange = NSRange(
location: 7, length: 6)
fullText.addAttribute(
NSAttributedString.Key.foregroundColor,
value: UIColor.systemGreen(),
range: amountRange)
fullText.addAttribute(
NSAttributedString.Key.font,
value: UIFont.boldSystemFont(ofSize: 22),
range: amountRange)
// Apply gray color to "per month" text
let periodRange = NSRange(
location: 14, length: 9)
fullText.addAttribute(
NSAttributedString.Key.foregroundColor,
value: UIColor.secondaryLabel,
range: periodRange)
label.attributedText = fullText
UITextView soporta enlaces interactivos en NSAttributedString. El atributo .link con un NSURL hace que el texto sea cliqueable. Para manejar toques, se usa el delegado UITextViewDelegate con el método textView(_:shouldInteractWith:in:interaction:). UITextView también soporta selección de texto y el uso de UIMenuController para operaciones estándar (copiar, buscar).
NSAttributedString soporta conversión desde HTML y RTF mediante NSAttributedString.DocumentType. Para cargar HTML, se usa el inicializador con el parámetro documentAttributes: NSAttributedString(data: htmlData, options: [.documentType: .html], documentAttributes: nil). Similarmente para RTF: .rtf o .rtfd. Este mecanismo es útil para mostrar contenido HTML sin WebView.
Para la exportación a HTML, se usa el método data(from:documentAttributes:) con un rango y tipo de documento. Exportación HTML: try attributedString.data(from: fullRange, documentAttributes: [.documentType: .html]). Los datos resultantes se pueden guardar en un archivo, enviar a un servidor o mostrar en un WebView. Durante la exportación, las fuentes, colores, alineación, listas — todos los atributos de formato — se convierten a estilos CSS.
El soporte de RTF es especialmente relevante para aplicaciones macOS, donde RTF es el formato estándar de texto enriquecido. iOS también soporta lectura y escritura de RTF pero no lo usa como formato principal. La diferencia entre RTF y RTFD: RTFD incluye recursos incrustados (imágenes) empaquetados en un directorio. NSAttributedString puede manejar ambos formatos a través de una interfaz única.
let htmlString = "<p><b>Bold<\/b> and <i>italic<\/i><\/p>"
guard let htmlData = htmlString.data(
using: String.Encoding.utf8) else { return }
let options: [NSAttributedString.DocumentReadingOptionKey: Any] = [
NSAttributedString.DocumentReadingOptionKey.documentType:
NSAttributedString.DocumentType.html
]
let attributedFromHTML =
try? NSAttributedString(
data: htmlData,
options: options,
documentAttributes: nil)
Preguntas frecuentes
NSString almacena solo una secuencia de caracteres Unicode sin información de formato. NSAttributedString almacena caracteres y para cada subrango contiene un diccionario de atributos (fuente, color, estilo). Al mostrarse, UIKit usa estos atributos para el renderizado, creando texto formateado.
La razón más común es usar la propiedad text en lugar de attributedText. Al asignar mediante text, todos los atributos se ignoran. La segunda razón: después de establecer attributedText, se cambian font, textColor o textAlignment de UILabel — estos cambios restablecen attributedText. Use solo attributedText para texto formateado.
Cree un NSMutableAttributedString y llame a addAttribute(.font, value: boldFont, range: boldRange) para cada segmento con una fuente diferente. Cada llamada aplica el atributo solo al rango especificado. Los caracteres restantes mantienen la fuente estándar u otra establecida previamente. Así se crean ejecuciones de atributos con diferentes fuentes.
Sí, NSAttributedString maneja correctamente texto multilínea, incluyendo caracteres de nueva línea ( ). UITextView y UILabel (con numberOfLines = 0) ajustan automáticamente el texto a una nueva línea. NSMutableParagraphStyle gestiona el interlineado, las sangrías y la alineación para cada párrafo independientemente.
Use NSMutableAttributedString con el atributo .foregroundColor para cada rango de color. Para texto rojo: addAttribute(.foregroundColor, value: UIColor.red, range: firstRange). Para azul: addAttribute(.foregroundColor, value: UIColor.blue, range: secondRange). Los colores se aplicarán solo a los rangos de caracteres especificados.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también