0

Lorsque je tente d'appliquer des attributs à la sous-chaîne, je parfois obtenir un crash dans le code suivant:NSMutableAttributedString Exception fatale: NSRangeException

// Dummy strings 
let originalString = "Some example string" 
let searchSubString = "exam" 

// Get range of sub-string for which new attributes are to be set. 
let rangeOfSubString: NSRange = (originalString.lowercaseString as NSString).rangeOfString(searchSubString.lowercaseString) 

// Apply new attributes to the sub-string in original string and show it in UILabel. 
let attributedOriginalString = NSMutableAttributedString(string: originalString, attributes: [NSForegroundColorAttributeName : UIColor.blueColor()]) 
attributedOriginalString.addAttribute(NSFontAttributeName, value: UIFont.systemFontOfSize(14.0), range: rangeOfSubString) 
attributedOriginalString.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(), range: rangeOfSubString) 
self.textLabel.attributedText = attributedOriginalString 

Et voici la trace de la pile:

Thread : Fatal Exception: NSRangeException 
0 CoreFoundation 0x26cbefef __exceptionPreprocess 
1 libobjc.A.dylib 0x35362c8b objc_exception_throw 
2 CoreFoundation 0x26cbef35 -[NSException initWithCoder:] 
3 Foundation 0x2793ac3b -[NSRLEArray objectAtIndex:effectiveRange:] 
4 Foundation 0x27954b2d -[NSConcreteMutableAttributedString addAttribute:value:range:] 

Je ne suis pas capable de le repro quoique, mais j'ai eu ce crash journal via crashlytics.

Le journal de l'accident semble dire que le rangeOfSubString est au-delà des limites de originalString, mais je ne pense pas que cela va jamais arriver. Est-ce que quelqu'un peut me signaler ce qui pourrait être la raison de l'accident?

+0

votre rangeOfSubString n'est pas correct –

+0

Quel est le problème? –

+0

Je pense que le searchSubString que vous utilisez est dynamique donc il ne vient pas dans la chaîne originalString donc l'accident se produit –

Répondre

0

Affichage ma réponse au cas où d'autres sont confrontés à ce genre de problème:

Remplacer

let rangeOfSubString: NSRange = (originalString.lowercaseString as NSString).rangeOfString(searchSubString.lowercaseString) 

avec

let rangeOfSubString: NSRange = (originalString as NSString).rangeOfString(searchSubString, options: .CaseInsensitiveSearch) 

La première façon de calculer plage sous-chaîne est mauvaise cause:

  • Il calcule la plage de sous-chaîne WRT en minuscules et applique les attributs de cette plage à la chaîne d'origine (non en minuscules). Mais la plage calculée en utilisant la méthode ci-dessus peut aller au-delà de la plage de chaîne d'origine en cas de caractères spéciaux, car les caractères en minuscules peuvent nécessiter plus de longueur que les versions majuscules et vice versa.

    -à-dire Longueur du caractère turc majuscule « I » est 1, alors que pour sa version « i » minuscule est 2.

  • Ex. Si nous cherchons « I » dans « Salut » (longueur = 2), la 1ère méthode vous donnera une plage (1, 2) car "İ" en minuscules nécessite la longueur = 2, mais si vous appliquez la plage (1, 2) à "H", elle dépassera sa portée est range (0, 2) ou s'il y a plus de caractères dans la chaîne d'origine comme "Hİabc", cela correspondra à "İa" qui est encore faux

  • Donc calculer la chaîne WRT originale comme plus tard j'ai besoin d'appliquer cette plage à la chaîne d'origine elle-même

Voir aussi la documentation d'Apple:

lowercaseString:

transformations de cas ne sont pas garantis symétriques ou pour produire des chaînes de la même longueur que les originaux.

lcString = [ChaîneMainsChaineBaseCourante];

pourrait ne pas être égale à cette déclaration :

lcString = [[myString uppercaseString] lowercaseString];

Par exemple, la forme majuscule de « ß » en allemand est « SS », donc la conversion « Straße » à majuscules, puis en minuscules, produit cette séquence de chaînes:

« Straße »

« STRASSE »

« strasse »

https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/#//apple_ref/occ/instp/NSString/lowercaseString