Tengo una NSAttributedString generados a partir de HTML que incluye algunos enlaces. El atribuida cadena se muestra en un UITextView. Deseo solicitar un estilo de fuente diferente para los enlaces y estoy configuración linkTextAttributes para esto. He añadido NSForegroundColorAttributeName, NSFontAttributeName y NSUnderlineStyleAttributeName. Por alguna razón el color de primer plano se aplica, pero el resto de los atributos no son.

myTextView.linkTextAttributes = [NSForegroundColorAttributeName : UIColor.redColor(), NSFontAttributeName : textLinkFont, NSUnderlineStyleAttributeName : NSUnderlineStyle.StyleNone.rawValue]

Ha nadie se enfrentó a esta y ¿cómo puedo cambiar el estilo de fuente para enlaces sin tener que aplicar en la línea de CSS en el HTML original? Gracias.

7 Comentarios

  1. 20

    No sé por qué linkTextAttributes no funciona para el nombre de la fuente. Pero podemos lograr esto mediante la actualización de los atributos de vínculo de la NSAttributedString. Compruebe el código de abajo.

            do {
            let htmlStringCode = "For more info <a href=\"http://www.samplelink.com/subpage.php?id=8\">Click here</a>"
    
            let string = try NSAttributedString(data: htmlStringCode.dataUsingEncoding(NSUTF8StringEncoding)!, options: [NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: NSUTF8StringEncoding], documentAttributes: nil)
    
            let newString = NSMutableAttributedString(attributedString: string)
            string.enumerateAttributesInRange(NSRange.init(location: 0, length: string.length), options: .Reverse) { (attributes : [String : AnyObject], range:NSRange, _) -> Void in
                if let _ = attributes[NSLinkAttributeName] {
                    newString.removeAttribute(NSFontAttributeName, range: range)
                    newString.addAttribute(NSFontAttributeName, value: UIFont.systemFontOfSize(30), range: range)
                }
            }
            textField.attributedText = newString
            textField.linkTextAttributes = [NSForegroundColorAttributeName : UIColor.redColor(), NSUnderlineStyleAttributeName : NSUnderlineStyle.StyleNone.rawValue]
    
        }catch {
        }

    Este es el objective-C código:

    NSDictionary *options = @{NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType};
    NSData *data = [html dataUsingEncoding:NSUnicodeStringEncoding allowLossyConversion:NO];
    
    NSAttributedString *attributedString = [[NSAttributedString alloc] initWithData:data options:options documentAttributes:nil error:nil];
    NSMutableAttributedString *attributedStringWithBoldLinks = [[NSMutableAttributedString alloc] initWithAttributedString:attributedString];
    
    [attributedString enumerateAttributesInRange:NSMakeRange(0, attributedString.string.length) options:NSAttributedStringEnumerationReverse usingBlock:^(NSDictionary<NSString *,id> * _Nonnull attrs, NSRange range, BOOL * _Nonnull stop) {
    
        if ([attrs objectForKey:NSLinkAttributeName]) {
            [attributedStringWithBoldLinks removeAttribute:NSFontAttributeName range:range];
            [attributedStringWithBoldLinks addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"YourFont-Bold" size:16.0] range:range];
        }
    }];
    
    self.linkTextAttributes = @{NSForegroundColorAttributeName : [UIColor redColor]};
    
    self.attributedText = attributedStringWithBoldLinks;

    UITextView linkTextAttributes atributo font no se aplica a NSAttributedString

    • Sirve al propósito. Pero si hay una lista de atributos que trabajar con linkTextAttributes, me encantaría saber!
  2. 3

    Esta es una forma rápida de 3 actualización de la respuesta anterior de @Arun Ammannaya

    guard let font = UIFont.init(name: "Roboto-Regular", size: 15) else {
        return
    }
    let newString = NSMutableAttributedString(attributedString: string)
    let range = NSRange(location:0,length: string.length)
    string.enumerateAttributes(in: range, options: .reverse, using: { (attributes : [String : Any], range : NSRange, _) -> Void in
        if let _ = attributes[NSLinkAttributeName] {
            newString.removeAttribute(NSFontAttributeName, range: range)
            newString.addAttribute(NSFontAttributeName, value: font, range: range)
        }
    })
    errorTextView.attributedText = newString
    errorTextView.linkTextAttributes = [NSForegroundColorAttributeName : UIColor.green, NSUnderlineStyleAttributeName : NSUnderlineStyle.styleSingle.rawValue]

    Esta es una forma rápida de 3 solución a @CTiPKA que prefiero ya que evita HTML

    guard let attributedString = errorTextView.attributedText else {
        return
    }
    guard let font = UIFont.init(name: "Roboto-Regular", size: 15) else {
       return
    }
    let newString = NSMutableAttributedString(attributedString: attributedString)
    
    let types: NSTextCheckingResult.CheckingType = [.link, .phoneNumber]
    
    guard let linkDetector = try? NSDataDetector(types: types.rawValue) else { return  }
    let range = NSRange(location:0,length: attributedString.length)
    
    linkDetector.enumerateMatches(in: attributedString.string, options: [], range: range, using: { (match : NSTextCheckingResult?,
        flags : NSRegularExpression.MatchingFlags, stop) in
    
        if let matchRange = match?.range {
            newString.removeAttribute(NSFontAttributeName, range: matchRange)
            newString.addAttribute(NSFontAttributeName, value: font, range: matchRange)
        }
    })
    errorTextView.attributedText = newString
  3. 3

    Por alguna razón el postprocesado atribuido cadena con enumerateAttributesInRange: no trabajo para mí.

    Lo que he usado NSDataDetector para detectar enlaces y enumerateMatchesInString:options:range:usingBlock: a poner mi estilo para todos los eslabones de la cadena.
    Aquí está mi función de procesamiento:

    + (void) postProcessTextViewLinksStyle:(UITextView *) textView {
       NSAttributedString *attributedString = textView.attributedText;
       NSMutableAttributedString *attributedStringWithItalicLinks = [[NSMutableAttributedString alloc] initWithAttributedString:attributedString];
    
       NSError *error = nil;
       NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink
                                                               error:&error];
    
       [detector enumerateMatchesInString:[attributedString string]
                               options:0
                                 range:NSMakeRange(0, [attributedString length])
                            usingBlock:^(NSTextCheckingResult *match, NSMatchingFlags flags, BOOL *stop){
                                NSRange matchRange = [match range];
                                NSLog(@"Links style postprocessing. Range (from: %lu, length: %lu )", (unsigned long)matchRange.location, (unsigned long)matchRange.length);
                                if ([match resultType] == NSTextCheckingTypeLink) {                                    
                                    [attributedStringWithItalicLinks removeAttribute:NSFontAttributeName range:matchRange];
                                    [attributedStringWithItalicLinks addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"YourFont-Italic" size:14.0f] range:matchRange];
                                }
                            }];
    
       textView.attributedText = attributedStringWithItalicLinks;
    }
    • Esta es la mejor respuesta en mi opinión
  4. 3

    Actualizado para Swift 4:

    let originalText = NSMutableAttributedString(attributedString: textView.attributedText)
    var newString = NSMutableAttributedString(attributedString: textView.attributedText)
    
    originalText.enumerateAttributes(in: NSRange(0..<originalText.length), options: .reverse) { (attributes, range, pointer) in
        if let _ = attributes[NSAttributedString.Key.link] {
            newString.removeAttribute(NSAttributedString.Key.font, range: range)
            newString.addAttribute(NSAttributedString.Key.font, value: UIFont.systemFont(ofSize: 30), range: range)
        }
    }
    
    self.textView.attributedText = newString // updates the text view on the vc
  5. 2

    para los casos simples: (sin horrible HTML, utilice):

        let linkTextAttributes : [String : Any] = [
            NSForegroundColorAttributeName: UIColor.red,
            NSUnderlineColorAttributeName: UIColor.magenta,
            NSUnderlineStyleAttributeName: NSUnderlineStyle.patternSolid.rawValue
        ]
    
        self.infoText.linkTextAttributes = linkTextAttributes
    • ¿No es esto exactamente lo mismo OP hizo excepto realiza una nueva variable y que directamente asignado.
  6. 0

    También hay una manera fácil de aplicar estilo para el texto si utiliza html – usted sólo tiene que añadir el estilo dentro del código html. Entonces usted no necesita preocuparse acerca de la configuración de los atributos del texto. Por ejemplo:

    NSString *html = [NSString stringWithFormat:@"<p style=\"font-family: Your-Font-Name; color: #344052; font-size: 15px\"><a style=\"color: #0A9FD2\" href=\"https://examplelink.com\">%@</a> %@ on %@</p>", name, taskName, timeString];
    NSDictionary *options = @{NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType};
    NSData *data = [html dataUsingEncoding:NSUTF8StringEncoding];
    
    NSAttributedString *attributedString = [[NSAttributedString alloc] initWithData:data options:options documentAttributes:nil error:nil];
  7. 0

    Swift 5 versión de Ryan Heitner es impresionante respuesta:

    guard let attributedString = textView.attributedText else { return }
    guard let linkFont = UIFont(name: "HelveticaNeue-Bold", size: 20.0) else { return }
    
    let newString = NSMutableAttributedString(attributedString: attributedString)
    let types: NSTextCheckingResult.CheckingType = [.link, .phoneNumber]
    
    guard let linkDetector = try? NSDataDetector(types: types.rawValue) else { return }
    let range = NSRange(location: 0, length: attributedString.length)
    
    linkDetector.enumerateMatches(in: attributedString.string, options: [], range: range, using: { (match: NSTextCheckingResult?, flags: NSRegularExpression.MatchingFlags, stop) in
        if let matchRange = match?.range {
            newString.removeAttribute(NSAttributedString.Key.font, range: matchRange)
            newString.addAttribute(NSAttributedString.Key.font, value: linkFont, range: matchRange)
        }
    })
    
    textView.attributedText = newString

Dejar respuesta

Please enter your comment!
Please enter your name here