string cocoa replace nsattributedstring foundation

Reemplace la subcadena de NSAttributedString con otra NSAttributedString



cocoa replace (8)

Quiero reemplazar una subcadena (por ejemplo, @"replace" ) de un NSAttributedString con otro NSAttributedString .

Estoy buscando un método equivalente al NSString de stringByReplacingOccurrencesOfString:withString: para NSAttributedString .


  1. Convierta su cadena atribuida en una instancia de NSMutableAttributedString .

  2. La cadena atribuible mutable tiene una propiedad mutableString . De acuerdo con la documentación:

    "El receptor rastrea los cambios en esta cadena y mantiene sus asignaciones de atributos actualizadas".

    De modo que puede usar la cadena mutable resultante para ejecutar el reemplazo con replaceOccurrencesOfString:withString:options:range:


Aquí es cómo puede cambiar la cadena de NSMutableAttributedString, conservando sus atributos:

Rápido:

// first we create a mutable copy of attributed text let originalAttributedText = nameLabel.attributedText?.mutableCopy() as! NSMutableAttributedString // then we replace text so easily let newAttributedText = originalAttributedText.mutableString.setString("new text to replace")

C objetivo:

NSMutableAttributedString *newAttrStr = [attribtedTxt.mutableString setString:@"new string"];


Con Swift 4 y iOS 11, puede usar una de las 2 formas siguientes para resolver su problema.

# 1. Usando NSMutableAttributedString replaceCharacters(in:with:) método

NSMutableAttributedString tiene un método llamado replaceCharacters(in:with:) . replaceCharacters(in:with:) tiene la siguiente declaración:

Reemplaza los caracteres y atributos en un rango dado con los caracteres y atributos de la cadena atribuida dada.

func replaceCharacters(in range: NSRange, with attrString: NSAttributedString)

El código de Playground a continuación muestra cómo usar replaceCharacters(in:with:) con el fin de reemplazar una subcadena de una instancia de NSMutableAttributedString con una nueva instancia de NSMutableAttributedString :

import UIKit // Set initial attributed string let initialString = "This is the initial string" let attributes = [NSAttributedStringKey.foregroundColor : UIColor.red] let mutableAttributedString = NSMutableAttributedString(string: initialString, attributes: attributes) // Set new attributed string let newString = "new" let newAttributes = [NSAttributedStringKey.underlineStyle : NSUnderlineStyle.styleSingle.rawValue] let newAttributedString = NSMutableAttributedString(string: newString, attributes: newAttributes) // Get range of text to replace guard let range = mutableAttributedString.string.range(of: "initial") else { exit(0) } let nsRange = NSRange(range, in: mutableAttributedString.string) // Replace content in range with the new content mutableAttributedString.replaceCharacters(in: nsRange, with: newAttributedString)

# 2. Usando el NSMutableString replaceOccurrences(of:with:options:range:)

NSMutableString tiene un método llamado replaceOccurrences(of:with:options:range:) . replaceOccurrences(of:with:options:range:) tiene la siguiente declaración:

Reemplaza todas las ocurrencias de una cadena dada en un rango dado con otra cadena dada, devolviendo el número de reemplazos.

func replaceOccurrences(of target: String, with replacement: String, options: NSString.CompareOptions = [], range searchRange: NSRange) -> Int

El código de Playground a continuación muestra cómo usar replaceOccurrences(of:with:options:range:) para reemplazar una subcadena de una instancia de NSMutableAttributedString con una nueva instancia de NSMutableAttributedString :

import UIKit // Set initial attributed string let initialString = "This is the initial string" let attributes = [NSAttributedStringKey.foregroundColor : UIColor.red] let mutableAttributedString = NSMutableAttributedString(string: initialString, attributes: attributes) // Set new string let newString = "new" // Replace replaceable content in mutableAttributedString with new content let totalRange = NSRange(location: 0, length: mutableAttributedString.string.count) _ = mutableAttributedString.mutableString.replaceOccurrences(of: "initial", with: newString, options: [], range: totalRange) // Get range of text that requires new attributes guard let range = mutableAttributedString.string.range(of: newString) else { exit(0) } let nsRange = NSRange(range, in: mutableAttributedString.string) // Apply new attributes to the text matching the range let newAttributes = [NSAttributedStringKey.underlineStyle : NSUnderlineStyle.styleSingle.rawValue] mutableAttributedString.setAttributes(newAttributes, range: nsRange)


En mi caso, la siguiente manera fue la única (probado en iOS9):

NSAttributedString *attributedString = ...; NSAttributedString *anotherAttributedString = ...; //the string which will replace while ([attributedString.mutableString containsString:@"replace"]) { NSRange range = [attributedString.mutableString rangeOfString:@"replace"]; [attributedString replaceCharactersInRange:range withAttributedString:anotherAttributedString]; }

Por supuesto, sería bueno encontrar otra forma mejor.


Encuentro que todas las demás respuestas no funcionan. Aquí es cómo reemplacé el contenido de una cadena NSAttributed en una extensión de categoría:

func stringWithString(stringToReplace:String, replacedWithString newStringPart:String) -> NSMutableAttributedString { let mutableAttributedString = mutableCopy() as! NSMutableAttributedString let mutableString = mutableAttributedString.mutableString while mutableString.containsString(stringToReplace) { let rangeOfStringToBeReplaced = mutableString.rangeOfString(stringToReplace) mutableAttributedString.replaceCharactersInRange(rangeOfStringToBeReplaced, withString: newStringPart) } return mutableAttributedString }


Tengo un requisito específico y lo fijo como a continuación. Esto podría ayudar a alguien.

Requisito: en el guión gráfico, el texto enriquecido se agrega directamente al atributo UITextView que contiene una palabra "Versión de la aplicación: 1.0". Ahora tengo que dinamizar el número de versión leyéndolo de info plist.

Solución: Se eliminó la versión número 1.0 del guión gráfico, solo se guardó la "Versión de la aplicación:" y se agregó el código siguiente.

NSAttributedString *attribute = self.firsttextView.attributedText; NSMutableAttributedString *mutableAttri = [[NSMutableAttributedString alloc] initWithAttributedString:attribute]; NSString *appVersionText = @"App Version:"; if ([[mutableAttri mutableString] containsString:appVersionText]) { NSDictionary* infoDict = [[NSBundle mainBundle] infoDictionary]; NSString* version = [infoDict objectForKey:@"CFBundleShortVersionString"]; NSString *newappversion = [NSString stringWithFormat:@"%@ %@",appVersionText,version] ; [[mutableAttri mutableString] replaceOccurrencesOfString:appVersionText withString:newappversion options:NSCaseInsensitiveSearch range:NSMakeRange(0, mutableAttri.length)]; self.firsttextView.attributedText = mutableAttri; }

¡¡Hecho!! Actualizado / modificado attributeText.


Tuve que escribir texto en negrita en las etiquetas <b> , aquí lo que hice:

- (NSAttributedString *)boldString:(NSString *)string { UIFont *boldFont = [UIFont boldSystemFontOfSize:14]; NSMutableAttributedString *attributedDescription = [[NSMutableAttributedString alloc] initWithString:string]; NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@".*?<b>(.*?)<///b>.*?" options:NSRegularExpressionCaseInsensitive error:NULL]; NSArray *myArray = [regex matchesInString:string options:0 range:NSMakeRange(0, string.length)] ; for (NSTextCheckingResult *match in myArray) { NSRange matchRange = [match rangeAtIndex:1]; [attributedDescription addAttribute:NSFontAttributeName value:boldFont range:matchRange]; } while ([attributedDescription.string containsString:@"<b>"] || [attributedDescription.string containsString:@"</b>"]) { NSRange rangeOfTag = [attributedDescription.string rangeOfString:@"<b>"]; [attributedDescription replaceCharactersInRange:rangeOfTag withString:@""]; rangeOfTag = [attributedDescription.string rangeOfString:@"</b>"]; [attributedDescription replaceCharactersInRange:rangeOfTag withString:@""]; } return attributedDescription; }


NSMutableAttributedString *result = [[NSMutableAttributedString alloc] initWithString:@"I am a boy."]; [result addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(0, [result length])]; NSMutableAttributedString *replace = [[NSMutableAttributedString alloc] initWithString:@"a"]; [replace addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0, [replace length])]; [result replaceCharactersInRange:NSMakeRange(5, [replace length]) withAttributedString:replace];