ios objective-c iphone ios8 nsmutableattributedstring

Subrayar parte de una cadena con NSMutableAttributedString en iOS 8 no funciona



objective-c iphone (7)

Agregue color para el atributo subrayado:

[attributedString addAttribute:NSUnderlineColorAttributeName value:[UIColor redColor] range:NSMakeRange(5, 6)];

Intento subrayar parte de una cadena, por ejemplo, una parte '' cadena '' en la cadena ''cadena de prueba ''. Estoy usando NSMutableAttributedString y mi solución funcionaba bien en iOS7 .

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:@"test string"]; [attributedString addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:NSMakeRange(5, 6)]; myLabel.attributedText = attributedString;

El problema es que mi solución ya no funciona en iOS8 . Después de pasar una hora probando múltiples variantes de NSMutableAttributedString , descubrí que esta solución solo funciona cuando el rango comienza con 0 (la longitud puede diferir). ¿Cuál es la razón para eso? ¿Cómo puedo solucionar esto?


Descubrí que si aplica UnderlineStyleNone a toda la cadena, puede aplicar selectivamente subrayado a una parte que comienza en el medio:

func underlinedString(string: NSString, term: NSString) -> NSAttributedString { let output = NSMutableAttributedString(string: string) let underlineRange = string.rangeOfString(term) output.addAttribute(NSUnderlineStyleAttributeName, value: NSUnderlineStyle.StyleNone.rawValue, range: NSMakeRange(0, string.length)) output.addAttribute(NSUnderlineStyleAttributeName, value: NSUnderlineStyle.StyleSingle.rawValue, range: underlineRange) return output }


Es septiembre de 2018, por lo que esta respuesta no se trata de iOS8, pero aún se relaciona con subrayar parte de una cadena.

Aquí hay una extensión de Swift 4 que subraya un término dado dentro de un myAttributedString ya compuesto

extension NSMutableAttributedString { func underline(term: String) { guard let underlineRange = string.range(of: term) else { return } let startPosition = string.distance(from: term.startIndex, to: underlineRange.lowerBound) let nsrange = NSRange(location: startPosition, length: term.count) addAttribute( .underlineStyle, value: NSUnderlineStyle.styleSingle.rawValue, range: nsrange) } }

Uso: myAttributedString.underline(term: "some term")


Utilicé la siguiente extensión (usando la función de Exidy) en el patio de recreo / simulador y funcionó bien, puede cambiar / agregar atributos según sus necesidades

extension NSMutableAttributedString { func changeWordsColour(terms:[NSString]) { let string = self.string as NSString self.addAttribute(NSForegroundColorAttributeName, value: UIColor.brownColor(), range: NSMakeRange(0, self.length)) for term in terms { let underlineRange = string.rangeOfString(term as String) self.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(), range: underlineRange) } } } let myStr = NSMutableAttributedString(string: "Change Words Colour") myStr.changeWordsColour(["change","Colour"])


Actualización: Al investigar esta pregunta: Mostrar NSMutableAttributedString en iOS 8 ¡Finalmente encontré la solución!

Debe agregar NSUnderlineStyleNone al comienzo de la cadena.

Swift 4.2 ( none se eliminó none ):

let attributedString = NSMutableAttributedString() attributedString.append(NSAttributedString(string: "test ", attributes: [.underlineStyle: 0])) attributedString.append(NSAttributedString(string: "s", attributes: [.underlineStyle: NSUnderlineStyle.single.rawValue])) attributedString.append(NSAttributedString(string: "tring", attributes: [.underlineStyle: 0]))

C objetivo:

NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] init]; [attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:@"test " attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleNone)}]]; [attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:@"s" attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle), NSBackgroundColorAttributeName: [UIColor clearColor]}]]; [attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:@"tring"]];

Otra ventaja de este enfoque es la ausencia de cualquier rango. Muy agradable para cadenas localizadas.

Parece que es un error de Apple :(


Versión Swift 5 de la respuesta de @ Joss con pocas modificaciones, agregando un NSMutableAttributedString devuelto, porque no podría usar la solución original sin él.

extension NSMutableAttributedString { func underline(term: String) -> NSMutableAttributedString { guard let underlineRange = string.range(of: term) else { return NSMutableAttributedString() } let startPosition = string.distance(from: term.startIndex, to: underlineRange.lowerBound) let nsrange = NSRange(location: startPosition, length: term.count) addAttribute( .underlineStyle, value: NSUnderlineStyle.single.rawValue, range: nsrange) return self } }

Uso:

let myUnderLinedText = "Hello World" let underLinedMutableString = NSMutableAttributedString(string: myUnderLinedText, attributes: titleAttributes).underline(term: myUnderLinedText)


NSMutableAttributedString *signUpString = [[NSMutableAttributedString alloc] initWithString:@"Not a member yet?Sign Up now"]; [signUpString appendAttributedString:[[NSAttributedString alloc] initWithString:@" "attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleNone)}]]; [signUpString addAttributes: @{NSForegroundColorAttributeName:UIColorFromRGB(0x43484B),NSUnderlineStyleAttributeName:[NSNumber numberWithInteger:NSUnderlineStyleSingle]} range:NSMakeRange(17,11)]; signUpLbl.attributedText = [signUpString copy];

Funciono para mi