web-dev-qa-db-fra.com

Changer les attributs des sous-chaînes dans un NSAttributedString

Cette question peut être un duplicata de celui-ci . Mais les réponses ne fonctionnent pas pour moi et je veux être plus précis.

J'ai une NSString, mais il me faut une NS(Mutable)AttributedString et certains mots de cette chaîne devraient avoir une couleur différente. J'ai essayé ceci:

NSString *text = @"This is the text and i want to replace something";

NSDictionary *attributes = @ {NSForegroundColorAttributeName : [UIColor redColor]};
NSMutableAttributedString *subString = [[NSMutableAttributedString alloc] initWithString:@"AND" attributes:attributes];

NSMutableAttributedString *newText = [[NSMutableAttributedString alloc] initWithString:text];

newText = [[newText mutableString] stringByReplacingOccurrencesOfString:@"and" withString:[subString mutableString]];

Le "et" doit être en majuscule et en rouge.

La documentation indique que mutableString conserve les mappages d'attributs. Mais avec mon objet de remplacement, je n'ai plus d'attributString à droite de l'affectation (à la dernière ligne de mon extrait de code).

Comment puis-je obtenir ce que je veux? ;)

16
mjay

La réponse de @Hyperlord fonctionnera, mais seulement s'il y a une occurrence du mot "et" dans la chaîne d'entrée. Quoi qu'il en soit, ce que je ferais serait d'utiliser le stringByReplacingOccurrencesOfString: de NSString initialement pour changer tous les "et" en "ET", puis d'utiliser un petit regex pour détecter les correspondances dans la chaîne attribuée et d'appliquer NSForegroundColorAttributeName à cette plage. Voici un exemple:

NSString *initial = @"This is the text and i want to replace something and stuff and stuff";
NSString *text = [initial stringByReplacingOccurrencesOfString:@"and" withString:@"AND"];

NSMutableAttributedString *mutableAttributedString = [[NSMutableAttributedString alloc] initWithString:text];

NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"(AND)" options:kNilOptions error:nil];


NSRange range = NSMakeRange(0,text.length);

[regex enumerateMatchesInString:text options:kNilOptions range:range usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {

    NSRange subStringRange = [result rangeAtIndex:1];
    [mutableAttributedString addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:subStringRange];
}];

Et enfin, appliquez simplement la chaîne attribuée à votre étiquette.

[myLabel setAttributedText:mutableAttributedString];
35
Mick MacCallum

Je pense que vous devriez créer une NSMutableAttributedString en utilisant la NSString existante, puis ajouter les attributs de style avec la NSRange appropriée afin de colorier les parties sur lesquelles vous souhaitez mettre l'accent, par exemple:

NSString *text = @"This is the text and i want to replace something";
NSMutableAttributedString *mutable = [[NSMutableAttributedString alloc] initWithString:text];
[mutable addAttribute: NSForegroundColorAttributeName value:[UIColor redColor] range:[text rangeOfString:@"and"]];

Attention, ceci vient de ma tête et n'est pas testé du tout ;-)

17
hyperlord

S'il vous plaît essayez ce code dans Swift 2 

var someStr = "This is the text and i want to replace something"
    someStr.replaceRange(someStr.rangeOfString("and")!, with: "AND")

    let attributeStr = NSMutableAttributedString(string: someStr)
    attributeStr.setAttributes([NSForegroundColorAttributeName: UIColor.yellowColor()], range: NSMakeRange(17, 3) )
    testLbl.attributedText = attributeStr
0
Masa S-AiYa

Voici une autre implémentation (dans Swift) utile si vous effectuez des manipulations plus complexes (telles que l'ajout/la suppression de caractères) avec votre chaîne attribuée:

let text = "This is the text and i want to replace something"
let mutAttrStr = NSMutableAttributedString(string: text)

let pattern = "\\band\\b"
let regex = NSRegularExpression(pattern: pattern, options: .allZeros, error: nil)

while let result = regex!.firstMatchInString(mutAttrStr.string, options: .allZeros, range:NSMakeRange(0, count(mutAttrStr.string)) {
    let substring = NSMutableAttributedString(attributedString: mutAttrStr.attributedSubstringFromRange(result.range))

    // manipulate substring attributes here
    substring.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(), range NSMakeRange(0, count(substring.string))

    mutAttrStr.replaceCharactersInRange(result.range, withAttributedString: substring)
}

Votre dernière chaîne attribuée devrait être:

let finalAttrStr = mutAttrStr.copy() as! NSAttributedString
0
ocwang