Aggiornare:
C'erano 2 parti chiave della mia domanda:
- Come creare un collegamento in cui il testo visualizzato per il collegamento selezionabile è diverso dal collegamento effettivo richiamato:
- Come impostare i collegamenti senza dover utilizzare il codice personalizzato per impostare gli attributi sul testo.
Si scopre che iOS 7 ha aggiunto la possibilità di caricare il testo attribuito da NSData
.
Ho creato una sottoclasse personalizzata UITextView
che sfrutta l' @IBInspectable
attributo e consente di caricare i contenuti da un file RTF direttamente in IB. Basta digitare il nome file in IB e la classe personalizzata fa il resto.
Ecco i dettagli:
In iOS 7, ha NSAttributedString
guadagnato il metodo initWithData:options:documentAttributes:error:
. Questo metodo consente di caricare un NSAttributedString da un oggetto NSData. È innanzitutto possibile caricare un file RTF in NSData, quindi utilizzare initWithData:options:documentAttributes:error:
per caricare tale NSData nella vista di testo. (Si noti che esiste anche un metodo initWithFileURL:options:documentAttributes:error:
che caricherà una stringa attribuita direttamente da un file, ma tale metodo è stato deprecato in iOS 9. È più sicuro utilizzare il metodo initWithData:options:documentAttributes:error:
, che non è stato deprecato.
Volevo un metodo che mi permettesse di installare collegamenti cliccabili nelle mie visualizzazioni di testo senza dover creare alcun codice specifico per i collegamenti che stavo usando.
La soluzione che mi è venuta in mente è stata quella di creare una sottoclasse personalizzata di UITextView che chiamo RTF_UITextView
e dargli una @IBInspectable
proprietà chiamata RTF_Filename
. Aggiungere il@IBInspectable
dell'attributo a una proprietà fa sì che Interface Builder esponga quella proprietà in "Impostazioni attributi". È quindi possibile impostare quel valore da IB senza codice personalizzato.
Ho anche aggiunto un @IBDesignable
attributo alla mia classe personalizzata. L' @IBDesignable
attributo dice a Xcode che dovrebbe installare una copia in esecuzione della classe di visualizzazione personalizzata nel builder Interface in modo che tu possa vederlo nella visualizzazione grafica della gerarchia della vista. () Sfortunatamente, per questa classe, la @IBDesignable
proprietà sembra essere traballante. Ha funzionato quando l'ho aggiunto per la prima volta, ma poi ho eliminato il contenuto in testo normale della mia vista di testo e i collegamenti cliccabili nella mia vista sono andati via e non sono stato in grado di recuperarli.)
Il mio codice RTF_UITextView
è molto semplice. Oltre ad aggiungere l' @IBDesignable
attributo e una RTF_Filename
proprietà con l' @IBInspectable
attributo, ho aggiunto un didSet()
metodo alla RTF_Filename
proprietà. Il didSet()
metodo viene chiamato ogni volta che il valore della RTF_Filename
proprietà cambia. Il codice per il didSet()
metodo è abbastanza semplice:
@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.");
}
}
}
}
}
Nota che se la proprietà @IBDesignable non ti consentirà in modo affidabile di visualizzare l'anteprima del testo con stile nel builder Interface, potrebbe essere meglio impostare il codice sopra come estensione di UITextView anziché come sottoclasse personalizzata. In questo modo è possibile utilizzarlo in qualsiasi vista di testo senza dover modificare la vista di testo nella classe personalizzata.
Vedi la mia altra risposta se è necessario supportare versioni iOS precedenti a iOS 7.
Puoi scaricare un progetto di esempio che include questa nuova classe da gitHub:
Progetto demo DatesInSwift su Github