Actualizar:
Había 2 partes clave en mi pregunta:
- Cómo hacer un enlace donde el texto que se muestra para el enlace en el que se puede hacer clic es diferente del enlace real que se invoca:
- Cómo configurar los enlaces sin tener que usar un código personalizado para establecer los atributos en el texto.
Resulta que iOS 7 agregó la capacidad de cargar texto atribuido desde NSData
.
Creé una subclase personalizada UITextView
que aprovecha la@IBInspectable
atributo y le permite cargar contenido de un archivo RTF directamente en IB. Simplemente escriba el nombre del archivo en IB y la clase personalizada hace el resto.
Aquí están los detalles:
En iOS 7, NSAttributedString
ganó el método initWithData:options:documentAttributes:error:
. Ese método le permite cargar una NSAttributedString desde un objeto NSData. Primero puede cargar un archivo RTF en NSData, luego usarlo initWithData:options:documentAttributes:error:
para cargar ese NSData en su vista de texto. (Tenga en cuenta que también hay un método initWithFileURL:options:documentAttributes:error:
que cargará una cadena atribuida directamente desde un archivo, pero ese método se desaprobó en iOS 9. Es más seguro usar el método initWithData:options:documentAttributes:error:
, que no se desaprobó.
Quería un método que me permitiera instalar enlaces clicables en mis vistas de texto sin tener que crear ningún código específico para los enlaces que estaba usando.
La solución que se me ocurrió fue crear una subclase personalizada de UITextView a la que llamo RTF_UITextView
y asignarle una @IBInspectable
propiedad llamada RTF_Filename
. Agregar el @IBInspectable
atributo a una propiedad hace que Interface Builder exponga esa propiedad en el "Inspector de atributos". Luego puede establecer ese valor desde IB sin código personalizado.
También agregué un @IBDesignable
atributo a mi clase personalizada. El @IBDesignable
atributo le dice a Xcode que debe instalar una copia en ejecución de su clase de vista personalizada en el generador de interfaces para que pueda verla en la visualización gráfica de su jerarquía de vistas. () Desafortunadamente, para esta clase, la @IBDesignable
propiedad parece ser escamosa. Funcionó cuando lo agregué por primera vez, pero luego eliminé el contenido de texto sin formato de mi vista de texto y los enlaces en los que se puede hacer clic desaparecieron y no he podido recuperarlos).
El código para mi RTF_UITextView
es muy simple. Además de agregar el @IBDesignable
atributo y una RTF_Filename
propiedad con el @IBInspectable
atributo, agregué un didSet()
método a la RTF_Filename
propiedad. El didSet()
método se llama cada vez que RTF_Filename
cambia el valor de la propiedad. El código para el didSet()
método es bastante simple:
@IBDesignable
class RTF_UITextView: UITextView
{
@IBInspectable
var RTF_Filename: String?
{
didSet(newValue)
{
//If the RTF_Filename is nil or the empty string, don't do anything
if ((RTF_Filename ?? "").isEmpty)
{
return
}
//Use optional binding to try to get an URL to the
//specified filename in the app bundle. If that succeeds, try to load
//NSData from the file.
if let fileURL = NSBundle.mainBundle().URLForResource(RTF_Filename, withExtension: "rtf"),
//If the fileURL loads, also try to load NSData from the URL.
let theData = NSData(contentsOfURL: fileURL)
{
var aString:NSAttributedString
do
{
//Try to load an NSAttributedString from the data
try
aString = NSAttributedString(data: theData,
options: [:],
documentAttributes: nil
)
//If it succeeds, install the attributed string into the field.
self.attributedText = aString;
}
catch
{
print("Nerp.");
}
}
}
}
}
Tenga en cuenta que si la propiedad @IBDesignable no le permitirá obtener una vista previa de su texto con estilo en el generador de interfaces, entonces sería mejor configurar el código anterior como una extensión de UITextView en lugar de una subclase personalizada. De esa manera, podría usarlo en cualquier vista de texto sin tener que cambiar la vista de texto a la clase personalizada.
Vea mi otra respuesta si necesita admitir versiones de iOS anteriores a iOS 7.
Puede descargar un proyecto de muestra que incluye esta nueva clase desde gitHub:
Proyecto de demostración DatesInSwift en Github