Mettre à jour:
Ma question comportait 2 éléments clés:
- Comment créer un lien où le texte affiché pour le lien cliquable est différent du lien réel qui est invoqué:
- Comment configurer les liens sans avoir à utiliser de code personnalisé pour définir les attributs sur le texte.
Il s'avère qu'iOS 7 a ajouté la possibilité de charger le texte attribué à partir de NSData
.
J'ai créé une sous-classe personnalisée UITextView
qui tire parti de l' @IBInspectable
attribut et vous permet de charger le contenu d'un fichier RTF directement dans IB. Vous tapez simplement le nom de fichier dans IB et la classe personnalisée fait le reste.
Voici les détails:
Dans iOS 7, a NSAttributedString
gagné la méthode initWithData:options:documentAttributes:error:
. Cette méthode vous permet de charger un NSAttributedString à partir d'un objet NSData. Vous pouvez d'abord charger un fichier RTF dans NSData, puis l'utiliser initWithData:options:documentAttributes:error:
pour charger ce NSData dans votre vue texte. (Notez qu'il existe également une méthode initWithFileURL:options:documentAttributes:error:
qui chargera une chaîne attribuée directement à partir d'un fichier, mais cette méthode a été déconseillée dans iOS 9. Il est plus sûr d'utiliser la méthode initWithData:options:documentAttributes:error:
, qui n'était pas déconseillée.
Je voulais une méthode qui me permette d'installer des liens cliquables dans mes vues de texte sans avoir à créer de code spécifique aux liens que j'utilisais.
La solution que j'ai trouvée était de créer une sous-classe personnalisée de UITextView que j'appelle RTF_UITextView
et de lui donner une @IBInspectable
propriété appelée RTF_Filename
. L'ajout de l' @IBInspectable
attribut à une propriété oblige Interface Builder à exposer cette propriété dans «l'inspecteur d'attributs». Vous pouvez ensuite définir cette valeur à partir d'IB sans code personnalisé.
J'ai également ajouté un @IBDesignable
attribut à ma classe personnalisée. L' @IBDesignable
attribut indique à Xcode qu'il doit installer une copie en cours d'exécution de votre classe de vue personnalisée dans le générateur d'interface afin que vous puissiez la voir dans l'affichage graphique de votre hiérarchie de vues. () Malheureusement, pour cette classe, la @IBDesignable
propriété semble floconneuse. Cela a fonctionné lorsque je l'ai ajouté pour la première fois, mais j'ai ensuite supprimé le contenu en texte brut de mon affichage de texte et les liens cliquables de mon affichage ont disparu et je n'ai pas pu les récupérer.)
Le code pour my RTF_UITextView
est très simple. En plus d'ajouter l' @IBDesignable
attribut et une RTF_Filename
propriété avec l' @IBInspectable
attribut, j'ai ajouté une didSet()
méthode à la RTF_Filename
propriété. La didSet()
méthode est appelée à chaque fois que la valeur de la RTF_Filename
propriété change. Le code de la didSet()
méthode est assez 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.");
}
}
}
}
}
Notez que si la propriété @IBDesignable ne vous permet pas de prévisualiser de manière fiable votre texte stylisé dans le générateur d'interface, il peut être préférable de définir le code ci-dessus comme une extension de UITextView plutôt qu'une sous-classe personnalisée. De cette façon, vous pouvez l'utiliser dans n'importe quelle vue de texte sans avoir à changer la vue de texte en classe personnalisée.
Voir mon autre réponse si vous devez prendre en charge les versions iOS avant iOS 7.
Vous pouvez télécharger un exemple de projet qui inclut cette nouvelle classe depuis gitHub:
Projet de démonstration DatesInSwift sur Github