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 UITextViewqui tire parti de l' @IBInspectableattribut 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 NSAttributedStringgagné 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_UITextViewet de lui donner une @IBInspectablepropriété appelée RTF_Filename. L'ajout de l' @IBInspectableattribut à 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 @IBDesignableattribut à ma classe personnalisée. L' @IBDesignableattribut 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 @IBDesignableproprié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_UITextViewest très simple. En plus d'ajouter l' @IBDesignableattribut et une RTF_Filenamepropriété avec l' @IBInspectableattribut, j'ai ajouté une didSet()méthode à la RTF_Filenamepropriété. La didSet()méthode est appelée à chaque fois que la valeur de la RTF_Filenameproprié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