¿Cómo puedo hacer clic en un enlace en un NSAttributedString?


Es trivial hacer hipervínculos clicables en un UITextView. Usted acaba de establecer la casilla de verificación "detectar enlaces" en la vista en IB, y detecta enlaces HTTP y los convierte en hipervínculos.

Sin embargo, eso todavía significa que lo que el usuario ve es el enlace "raw". Los archivos RTF y HTML le permiten configurar una cadena legible por el usuario con un enlace "detrás" de ella.

Es fácil instalar texto atribuido en una vista de texto (o un UILabel o UITextField, para el caso.) Sin embargo, cuando ese texto atribuido incluye un enlace, no se puede hacer clic.

¿Hay una manera de hacer que el texto legible por el usuario UITextView, UILabel ¿o UITextField?

El marcado es diferente en SO, pero aquí está la idea general. Lo que quiero es texto como este:

Esta transformación se generó con Face Dancer, haga clic para verla en la app store.

Lo único que puedo conseguir es esto:

Esta transformación se generó con Face Dancer, Haga clic en http://example.com/facedancer para ver en la app store.

Author: Tamás Sengel, 2014-02-07

20 answers

Use NSMutableAttributedString.

NSMutableAttributedString * str = [[NSMutableAttributedString alloc] initWithString:@"Google"];
[str addAttribute: NSLinkAttributeName value: @"http://www.google.com" range: NSMakeRange(0, str.length)];
yourTextView.attributedText = str;

Edit :

Esto no se trata directamente de la pregunta, pero solo para aclarar, UITextField y UILabel no admite la apertura de URLs. Si quieres usar UILabel con enlaces puedes comprobar TTTAttributedLabel.

También debe establecer dataDetectorTypes el valor de su UITextView a UIDataDetectorTypeLink o UIDataDetectorTypeAll para abrir URL cuando se hace clic. O puede usar el método delegado como se sugiere en los comentarios.

 133
Author: ujell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-27 08:28:02

Encontré esto muy útil, pero necesitaba hacerlo en bastantes lugares, así que he envuelto mi enfoque en una simple extensión a NSMutableAttributedString:

Swift 3

extension NSMutableAttributedString {

    public func setAsLink(textToFind:String, linkURL:String) -> Bool {

        let foundRange = self.mutableString.range(of: textToFind)
        if foundRange.location != NSNotFound {
            self.addAttribute(.link, value: linkURL, range: foundRange)
            return true
        }
        return false
    }
}

Swift 2

import Foundation

extension NSMutableAttributedString {

   public func setAsLink(textToFind:String, linkURL:String) -> Bool {

       let foundRange = self.mutableString.rangeOfString(textToFind)
       if foundRange.location != NSNotFound {
           self.addAttribute(NSLinkAttributeName, value: linkURL, range: foundRange)
           return true
       }
       return false
   }
}

Ejemplo de uso:

let attributedString = NSMutableAttributedString(string:"I love stackoverflow!")
let linkWasSet = attributedString.setAsLink("stackoverflow", linkURL: "http://stackoverflow.com")

if linkWasSet {
    // adjust more attributedString properties
}

Objective-C

Acabo de cumplir con el requisito de hacer lo mismo en un proyecto de Objective-C puro, así que aquí está la categoría Objective-C.

@interface NSMutableAttributedString (SetAsLinkSupport)

- (BOOL)setAsLink:(NSString*)textToFind linkURL:(NSString*)linkURL;

@end


@implementation NSMutableAttributedString (SetAsLinkSupport)

- (BOOL)setAsLink:(NSString*)textToFind linkURL:(NSString*)linkURL {

     NSRange foundRange = [self.mutableString rangeOfString:textToFind];
     if (foundRange.location != NSNotFound) {
         [self addAttribute:NSLinkAttributeName value:linkURL range:foundRange];
         return YES;
     }
     return NO;
}

@end

Ejemplo de uso:

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:"I love stackoverflow!"];

BOOL linkWasSet = [attributedString setAsLink:@"stackoverflow" linkURL:@"http://stackoverflow.com"];

if (linkWasSet) {
    // adjust more attributedString properties
}
 96
Author: Karl Nosworthy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-20 20:38:58

Mejora menor de la solución de ujell: Si usa NSURL en lugar de NSString, puede usar cualquier URL (por ejemplo, url personalizadas)

NSURL *URL = [NSURL URLWithString: @"whatsapp://app"];
NSMutableAttributedString * str = [[NSMutableAttributedString alloc] initWithString:@"start Whatsapp"];
[str addAttribute: NSLinkAttributeName value:URL range: NSMakeRange(0, str.length)];
yourTextField.attributedText = str;

Diviértete!

 26
Author: Hans One,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-21 14:07:48

Acabo de crear una subclase de UILabel para abordar especialmente estos casos de uso. Puede agregar múltiples enlaces fácilmente y definir diferentes controladores para ellos. También admite resaltar el enlace presionado cuando aterriza para obtener retroalimentación táctil. Por favor refiérase a https://github.com/null09264/FRHyperLabel .

En su caso, el código puede ser así:

FRHyperLabel *label = [FRHyperLabel new];

NSString *string = @"This morph was generated with Face Dancer, Click to view in the app store.";
NSDictionary *attributes = @{NSFontAttributeName: [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]};

label.attributedText = [[NSAttributedString alloc]initWithString:string attributes:attributes];

[label setLinkForSubstring:@"Face Dancer" withLinkHandler:^(FRHyperLabel *label, NSString *substring){
    [[UIApplication sharedApplication] openURL:aURL];
}];

Ejemplo de captura de pantalla (el controlador está configurado para mostrar una alerta en lugar de abrir una url en este case)

facedancer

 26
Author: Jinghan Wang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-29 15:11:58

Yo también tenía un requisito similar, inicialmente usé UILabel y luego me di cuenta de que UITextView es mejor. Hice que UITextView se comporte como UILabel deshabilitando la interacción y el desplazamiento e hice un método de categoría para NSMutableAttributedString para establecer el enlace al texto igual que lo que Karl había hecho (+1 para eso) esta es mi versión de obj c

-(void)setTextAsLink:(NSString*) textToFind withLinkURL:(NSString*) url
{
    NSRange range = [self.mutableString rangeOfString:textToFind options:NSCaseInsensitiveSearch];

    if (range.location != NSNotFound) {

        [self addAttribute:NSLinkAttributeName value:url range:range];
        [self addAttribute:NSForegroundColorAttributeName value:[UIColor URLColor] range:range];
    }
}

Puede usar el delegado a continuación para manejar la acción

- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)url inRange:(NSRange)characterRange
{
    // do the task
    return YES;
}
 16
Author: anoop4real,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-31 06:42:07

Use UITextView soporta Enlaces clicables. Crear cadena atribuida usando el siguiente código

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:strSomeTextWithLinks];

Luego establece el texto UITextView de la siguiente manera

NSDictionary *linkAttributes = @{NSForegroundColorAttributeName: [UIColor redColor],

                                 NSUnderlineColorAttributeName: [UIColor blueColor],

                                 NSUnderlineStyleAttributeName: @(NSUnderlinePatternSolid)};

customTextView.linkTextAttributes = linkAttributes; // customizes the appearance of links
textView.attributedText = attributedString;

Asegúrese de habilitar el comportamiento "seleccionable" de UITextView en XIB.

 14
Author: Nitheesh George,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-27 08:42:39

El corazón de mi pregunta era que quería poder crear enlaces clicables en vistas de texto/campos/etiquetas sin tener que escribir código personalizado para manipular el texto y agregar los enlaces. Quería que fuera basado en datos.

Finalmente descubrí cómo hacerlo. El problema es que IB no respeta los enlaces incrustados.

Además, la versión iOS de NSAttributedString no le permite inicializar una cadena atribuida desde un archivo RTF. La versión de OS X de NSAttributedString tiene un inicializador que toma un archivo RTF como entrada.

NSAttributedString cumple con el protocolo NSCoding, por lo que puede convertirlo a/desde NSData

He creado una herramienta de línea de comandos de OS X que toma un archivo RTF como entrada y genera un archivo con la extensión .datos que contienen los NSData de NSCoding. Luego pongo el .archivo de datos en mi proyecto y añadir un par de líneas de código que carga el texto en la vista. El código se ve así (este proyecto estaba en Swift):

/*
If we can load a file called "Dates.data" from the bundle and convert it to an attributed string,
install it in the dates field. The contents contain clickable links with custom URLS to select
each date.
*/
if
  let datesPath = NSBundle.mainBundle().pathForResource("Dates", ofType: "data"),
  let datesString = NSKeyedUnarchiver.unarchiveObjectWithFile(datesPath) as? NSAttributedString
{
  datesField.attributedText = datesString
}

Para aplicaciones que usan una gran cantidad de texto formateado, creo una regla de compilación que le dice a Xcode que todos los .los archivos rtf en una carpeta dada son fuente y el .los archivos de datos son la salida. Una vez que lo hago, simplemente añado .archivos rtf al directorio designado (o editar archivos existentes) y el proceso de compilación descubre que son nuevos/actualizados, ejecuta la herramienta de línea de comandos y copia los archivos en el paquete de aplicaciones. Funciona muy bien.

Escribí una entrada de blog que enlaza a un proyecto de muestra (Swift) que demuestra la técnica. Puedes verlo aquí:

Crear URLs clicables en un campo Uitext que se abra en tu app

 10
Author: Duncan C,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-26 17:01:12

Ejemplo de Swift 3 para detectar acciones en toques de texto atribuidos

Https://stackoverflow.com/a/44226491/5516830

let termsAndConditionsURL = TERMS_CONDITIONS_URL;
let privacyURL            = PRIVACY_URL;

override func viewDidLoad() {
    super.viewDidLoad()

    self.txtView.delegate = self
    let str = "By continuing, you accept the Terms of use and Privacy policy"
    let attributedString = NSMutableAttributedString(string: str)
    var foundRange = attributedString.mutableString.range(of: "Terms of use") //mention the parts of the attributed text you want to tap and get an custom action
    attributedString.addAttribute(NSLinkAttributeName, value: termsAndConditionsURL, range: foundRange)
    foundRange = attributedString.mutableString.range(of: "Privacy policy")
    attributedString.addAttribute(NSLinkAttributeName, value: privacyURL, range: foundRange)
    txtView.attributedText = attributedString
}

func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let vc = storyboard.instantiateViewController(withIdentifier: "WebView") as! SKWebViewController

    if (URL.absoluteString == termsAndConditionsURL) {
        vc.strWebURL = TERMS_CONDITIONS_URL
        self.navigationController?.pushViewController(vc, animated: true)
    } else if (URL.absoluteString == privacyURL) {
        vc.strWebURL = PRIVACY_URL
        self.navigationController?.pushViewController(vc, animated: true)
    }
    return false
}

Al igual que wise, puede agregar cualquier acción que desee con el método shouldInteractWith URL UITextFieldDelegate.

Salud!!

 8
Author: Akila Wasala,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-28 11:17:18

Swift 4:

var string = "Google"
var attributedString = NSMutableAttributedString(string: string, attributes:[NSAttributedStringKey.link: URL(string: "http://www.google.com")!])

yourTextView.attributedText = attributedString

Swift 3.1:

var string = "Google"
var attributedString = NSMutableAttributedString(string: string, attributes:[NSLinkAttributeName: URL(string: "http://www.google.com")!])

yourTextView.attributedText = attributedString
 7
Author: Bill Chan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-06 13:13:17

He escrito un método, que agrega un enlace (linkString) a una cadena (fullString) con una determinada url (urlString):

- (NSAttributedString *)linkedStringFromFullString:(NSString *)fullString withLinkString:(NSString *)linkString andUrlString:(NSString *)urlString
{
    NSRange range = [fullString rangeOfString:linkString options:NSLiteralSearch];
    NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:fullString];

    NSMutableParagraphStyle *paragraphStyle = NSMutableParagraphStyle.new;
    paragraphStyle.alignment = NSTextAlignmentCenter;
    NSDictionary *attributes = @{NSForegroundColorAttributeName:RGB(0x999999),
                                 NSFontAttributeName:[UIFont fontWithName:@"HelveticaNeue-Light" size:10],
                                 NSParagraphStyleAttributeName:paragraphStyle};
    [str addAttributes:attributes range:NSMakeRange(0, [str length])];
    [str addAttribute: NSLinkAttributeName value:urlString range:range];

    return str;
}

Deberías llamarlo así:

NSString *fullString = @"A man who bought the Google.com domain name for $12 and owned it for about a minute has been rewarded by Google for uncovering the flaw.";
NSString *linkString = @"Google.com";
NSString *urlString = @"http://www.google.com";

_youTextView.attributedText = [self linkedStringFromFullString:fullString withLinkString:linkString andUrlString:urlString];
 4
Author: wzbozon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-16 16:37:30

Simplemente encuentre una solución sin código para UITextView: introduzca la descripción de la imagen aquí

Habilitar Detección- > Opciones de enlaces, la URL y también el correo electrónico serán detectados y se puede hacer clic!

 3
Author: Bill Chan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-08 20:06:39

Actualización:

Había 2 partes clave en mi pregunta:{[28]]}

  1. Cómo hacer un enlace donde el texto mostrado para el enlace clicable es diferente del enlace real que se invoca:
  2. Cómo configurar los enlaces sin tener que usar código personalizado para establecer los atributos en el texto.

Resulta que iOS 7 agregó la capacidad de cargar texto atribuido desde NSData.

He creado una subclase personalizada de UITextView que aprovecha el atributo @IBInspectable y le permite cargar el contenido de un archivo RTF directamente en IB. Simplemente escriba el nombre del archivo en IB y la clase personalizada hará el resto.

Aquí están los detalles:

En iOS 7, NSAttributedString ganó el método initWithData:options:documentAttributes:error:. Este método le permite cargar un NSAttributedString desde un objeto NSData. Primero puede cargar un archivo RTF en NSData, luego usar 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 fue obsoleto en iOS 9. Es más seguro usar el método initWithData:options:documentAttributes:error:, que no fue obsoleto.

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 que llamo RTF_UITextView y darle una propiedad @IBInspectable llamada RTF_Filename. Agregar el atributo @IBInspectable a una propiedad hace que Interface Builder exponga esa propiedad en el "Inspector de Atributos."A continuación, puede establecer ese valor desde IB sin código personalizado.

También agregué un atributo @IBDesignable a mi clase personalizada. El atributo @IBDesignable le dice a Xcode que debe instalar una copia en ejecución de su clase de vista personalizada en Interface builder para que pueda verla en la visualización gráfica de su jerarquía de vistas. () Desafortunadamente, para esta clase, la propiedad @IBDesignable parece ser escamosa. Funcionó la primera vez que lo agregué, pero luego eliminé el contenido de texto sin formato de mi vista de texto y los enlaces clicables en mi vista desaparecieron y no he sido capaz de recuperarlos.)

El código para mi RTF_UITextView es muy simple. Además de agregar el atributo @IBDesignable y una propiedad RTF_Filename con el atributo @IBInspectable, agregué un método didSet() a la propiedad RTF_Filename. El método didSet() se llama cada vez que cambia el valor de la propiedad RTF_Filename. El código para el método didSet() 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 va a permitir de forma fiable para obtener una vista previa de su texto con estilo en Interface Builder, entonces podría ser 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.

Consulte mi otra respuesta si necesita admitir versiones de iOS anteriores a iOS 7.

Puedes descargar un proyecto de ejemplo que incluye esta nueva clase desde GitHub:

DatesInSwift demo project en Github

 3
Author: Duncan C,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-02 02:08:49

Versión Swift:

    // Attributed String for Label
    let plainText = "Apkia"
    let styledText = NSMutableAttributedString(string: plainText)
    // Set Attribuets for Color, HyperLink and Font Size
    let attributes = [NSFontAttributeName: UIFont.systemFontOfSize(14.0), NSLinkAttributeName:NSURL(string: "http://apkia.com/")!, NSForegroundColorAttributeName: UIColor.blueColor()]
    styledText.setAttributes(attributes, range: NSMakeRange(0, plainText.characters.count))
    registerLabel.attributedText = styledText
 3
Author: ioopl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-10 14:42:02

Necesitaba seguir usando un UILabel puro, así llamado esto de mi reconocedor de tap (esto se basa en la respuesta de malex aquí: Índice de caracteres en el punto de contacto para UILabel)

UILabel* label = (UILabel*)gesture.view;
CGPoint tapLocation = [gesture locationInView:label];

// create attributed string with paragraph style from label

NSMutableAttributedString* attr = [label.attributedText mutableCopy];
NSMutableParagraphStyle* paragraphStyle = [NSMutableParagraphStyle new];
paragraphStyle.alignment = label.textAlignment;

[attr addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, label.attributedText.length)];

// init text storage

NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:attr];
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
[textStorage addLayoutManager:layoutManager];

// init text container

NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:CGSizeMake(label.frame.size.width, label.frame.size.height+100) ];
textContainer.lineFragmentPadding  = 0;
textContainer.maximumNumberOfLines = label.numberOfLines;
textContainer.lineBreakMode        = label.lineBreakMode;

[layoutManager addTextContainer:textContainer];

// find tapped character

NSUInteger characterIndex = [layoutManager characterIndexForPoint:tapLocation
                                                  inTextContainer:textContainer
                         fractionOfDistanceBetweenInsertionPoints:NULL];

// process link at tapped character

[attr enumerateAttributesInRange:NSMakeRange(characterIndex, 1)
                                         options:0
                                      usingBlock:^(NSDictionary<NSString *,id> * _Nonnull attrs, NSRange range, BOOL * _Nonnull stop) {
                                          if (attrs[NSLinkAttributeName]) {
                                              NSString* urlString = attrs[NSLinkAttributeName];
                                              NSURL* url = [NSURL URLWithString:urlString];
                                              [[UIApplication sharedApplication] openURL:url];
                                          }
                                      }];
 3
Author: masty,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:51

Una adición rápida a la descripción original de Duncan C vis-á-vie IB comportamiento. Él escribe: "Es trivial hacer hipervínculos clicables en un UITextView. Usted acaba de establecer la casilla de verificación "detectar enlaces" en la vista en IB, y detecta enlaces http y los convierte en hipervínculos."

Mi experiencia (al menos en xcode 7) es que también tiene que deslicar el comportamiento "Editable" para que las URL sean detectadas y se pueda hacer clic.

 2
Author: sakumatto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-16 07:43:39

Si desea usar el NSLinkAttributeName en un UITextView, entonces puede considerar usar la biblioteca AttributedTextView. Es una subclase UITextView que hace que sea muy fácil de manejar estos. Para más información ver: https://github.com/evermeer/AttributedTextView

Puede hacer que cualquier parte del texto interactúe de esta manera (donde textView1 es un IBOutlet UITextView):

textView1.attributer =
    "1. ".red
    .append("This is the first test. ").green
    .append("Click on ").black
    .append("evict.nl").makeInteract { _ in
        UIApplication.shared.open(URL(string: "http://evict.nl")!, options: [:], completionHandler: { completed in })
    }.underline
    .append(" for testing links. ").black
    .append("Next test").underline.makeInteract { _ in
        print("NEXT")
    }
    .all.font(UIFont(name: "SourceSansPro-Regular", size: 16))
    .setLinkColor(UIColor.purple) 

Y para manejar hashtags y menciones puedes usar código como este:

textView1.attributer = "@test: What #hashtags do we have in @evermeer #AtributedTextView library"
    .matchHashtags.underline
    .matchMentions
    .makeInteract { link in
        UIApplication.shared.open(URL(string: "https://twitter.com\(link.replacingOccurrences(of: "@", with: ""))")!, options: [:], completionHandler: { completed in })
    }
 1
Author: Edwin Vermeer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-01 13:30:37

La excelente biblioteca de @AliSoftware OHAttributedStringAdditions hace que sea fácil agregar enlaces en UILabel aquí está la documentación: https://github.com/AliSoftware/OHAttributedStringAdditions/wiki/link-in-UILabel

 0
Author: iGranDav,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:37

Si desea una subcadena activa en su UITextView, puede usar mi vista de texto extendida... es corto y sencillo. Puedes editarlo como quieras.

Resultado: introduzca la descripción de la imagen aquí

Código: https://github.com/marekmand/ActiveSubstringTextView

 0
Author: Marek Manduch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-27 11:01:27
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:strSomeTextWithLinks];

NSDictionary *linkAttributes = @{NSForegroundColorAttributeName: [UIColor redColor],   
                                 NSUnderlineColorAttributeName: [UIColor blueColor],
                                 NSUnderlineStyleAttributeName: @(NSUnderlinePatternSolid)};

customTextView.linkTextAttributes = linkAttributes; // customizes the appearance of links
textView.attributedText = attributedString;

PUNTOS CLAVE:

  • Asegúrese de habilitar el comportamiento "seleccionable" de UITextView en XIB.
  • Asegúrese de deshabilitar el comportamiento "editable" del UITextView en XIB.
 0
Author: Shashank Sharma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-12 06:39:30

Use UITextView y establezca dataDetectorTypes para Link.

Así:

testTextView.editable = false 
testTextView.dataDetectorTypes = .link

Si desea detectar enlace, número de teléfono, dirección, etc..entonces

testTextView.dataDetectorTypes = .all
 0
Author: Adarsh G J,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-27 06:51:22