Atualizar:
Havia duas partes principais da minha pergunta:
- Como criar um link em que o texto mostrado para o link clicável seja diferente do link real que é chamado:
- Como configurar os links sem precisar usar código personalizado para definir os atributos no texto.
Acontece que o iOS 7 adicionou a capacidade de carregar o texto atribuído NSData
.
Criei uma subclasse personalizada UITextView
que aproveita o @IBInspectable
atributo e permite carregar o conteúdo de um arquivo RTF diretamente no IB. Você simplesmente digita o nome do arquivo no IB e a classe personalizada faz o resto.
Aqui estão os detalhes:
No iOS 7, NSAttributedString
ganhou o métodoinitWithData:options:documentAttributes:error:
. Esse método permite carregar um NSAttributedString a partir de um objeto NSData. Você pode primeiro carregar um arquivo RTF no NSData e depois usá-lo initWithData:options:documentAttributes:error:
para carregá-lo na exibição de texto. (Observe que também há um método initWithFileURL:options:documentAttributes:error:
que carrega uma sequência atribuída diretamente de um arquivo, mas esse método foi preterido no iOS 9. É mais seguro usar o método initWithData:options:documentAttributes:error:
, que não foi preterido.
Eu queria um método que me permitisse instalar links clicáveis nos meus modos de exibição de texto sem precisar criar nenhum código específico para os links que eu estava usando.
A solução que encontrei foi criar uma subclasse personalizada do UITextView que eu chamo RTF_UITextView
e fornecer uma@IBInspectable
propriedade chamada RTF_Filename
. A adição do @IBInspectable
atributo a uma propriedade faz com que o Interface Builder exponha essa propriedade no "Attributes Inspector". Em seguida, você pode definir esse valor no IB sem código personalizado.
Também adicionei um @IBDesignable
atributo à minha classe personalizada. o@IBDesignable
atributo diz ao Xcode que ele deve instalar uma cópia em execução da sua classe de visualização customizada no construtor Interface, para que você possa vê-la na exibição gráfica da sua hierarquia de visualizações. () Infelizmente, para esta classe, a @IBDesignable
propriedade parece ser esquisita. Funcionou quando o adicionei pela primeira vez, mas excluí o conteúdo de texto sem formatação da minha exibição de texto e os links clicáveis desapareceram e não consegui recuperá-los.)
O código para o meu RTF_UITextView
é muito simples. Além de adicionar o @IBDesignable
atributo e uma RTF_Filename
propriedade ao @IBInspectable
atributo, adicionei um didSet()
método à RTF_Filename
propriedade O didSet()
método é chamado sempre que o valor da RTF_Filename
propriedade é alterado. O código para o didSet()
método é bastante simples:
@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.");
}
}
}
}
}
Observe que, se a propriedade @IBDesignable não permitir a visualização confiável do texto com estilo no construtor de interface, será melhor configurar o código acima como uma extensão do UITextView em vez de uma subclasse personalizada. Dessa forma, você pode usá-lo em qualquer visualização de texto sem precisar alterar a visualização de texto para a classe personalizada.
Veja minha outra resposta se precisar oferecer suporte a versões do iOS anteriores ao iOS 7.
Você pode baixar um projeto de amostra que inclua essa nova classe no gitHub:
Projeto de demonstração DatesInSwift no Github