2010-09-05 8 views
1

J'ai récemment travaillé sur un système de mise en évidence de syntaxe facile à utiliser pour un projet personnel. Jusqu'à présent, tout fonctionne correctement en trouvant la gamme de chaînes spécifiques et en soulignant cette plage dans NSTextView. Tout fonctionne jusqu'à ce que vous essayez de taper un mot surligné deux fois, ce qui provoque l'erreur démontré ci-dessous:Existe-t-il un moyen d'obtenir un NSArray de NSRanges pour une occurrence de NSString dans un autre NSString?

<div class="container"> 
    <div> <!-- This <div> would not get highlighted --> 
     Hello World 
    </div> 
</div> <!-- this </div> would not get highlighted --> 

je crois que cela se produit parce que je ne fais que recevoir la première occurrence d'un NSString en utilisant la méthode de rangeOfString, et que raison, seul le premier élément en surbrillance est en surbrillance.

Désolé pour la longue explication! Quoi qu'il en soit, je me demandais s'il y avait une méthode rangesOfString ou quelque chose de similaire qui peut me donner un NSArray de NSRanges pour chaque occurrence d'un NSString dans un autre NSString. Ci-dessous la ligne de code que je utilise pour obtenir ma gamme actuellement:

NSString *textViewString = [textView string]; 
NSString *textToHighlight = @"<div>"; 
NSRange area; 

area.location = 0; 
area.length = [textViewString length]; 

NSRange range = [textViewString rangeOfString: textToHighlight 
             options: NSCaseInsensitiveSearch 
             range: area]; 

Ce que je voudrais est quelque chose comme ceci:

NSString *textViewString = [textView string]; 
NSString *textToHighlight = @"<div>"; 
NSRange area; 

area.location = 0; 
area.length = [textViewString length]; 

NSArray *ranges = [textViewString rangesOfString: textToHighlight 
             options: NSCaseInsensitiveSearch 
              range: area]; 

int i; 
int total = [ranges count]; 
for (i = 0; i < total; i++) { 
    NSRange occurrence = [ranges objectAtIndex: i]; 
    // Apply color highlighting here 
} 

Si cela est impossible, quelqu'un pourrait-il s'il vous plaît me diriger dans la bonne direction ou suggérer une autre façon de faire de la coloration syntaxique? Je vous remercie!

+0

Plutôt que d'écrire le vôtre, pourquoi ne pas utiliser l'un des frameworks open source existants? par exemple. http://github.com/mugginsoft/Fragaria –

+0

Je vais devoir vérifier cela, merci! –

Répondre

3

Il n'existe pas de méthode de ce type. Vous pouvez utiliser rangeOfSubstring:options:range: pour obtenir chaque match, et affiner la gamme que vous allez: Après chaque match, vous changez l'emplacement de la plage de recherche au caractère après (emplacement + longueur de) la plage de correspondance et de réduire la longueur de la plage de recherche .


Dans le monde basé sur des blocs-moderne, il est pas difficile d'écrire an “enumerate substrings that match…” method qui fait ce qui précède que sa mise en œuvre. Voici ce que cela ressemble:

- (NSUInteger) enumerateSubstringsMatchingString_PRH:(NSString *)stringToFind 
    options:(NSStringCompareOptions)mask 
    usingBlock:(void (^)(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop))block 
{ 
    NSUInteger count = 0; 

    NSUInteger selfLength = self.length; 
    NSRange searchRange = { 0, selfLength }; 
    NSRange foundRange; 
    BOOL stop = NO; 
    while ((! stop) && (foundRange = [self rangeOfString:stringToFind options:mask range:searchRange]).location != NSNotFound) { 
     ++count; 
     if (block != NULL) { 
      @autoreleasepool { 
       NSString *substring = [self substringWithRange:foundRange]; 
       block(substring, foundRange, /*TODO include terminators and separators in enclosingRange as described in enumerateSubstringsWithOptions:: docs*/ foundRange, &stop); 
      } 
     } 
     searchRange.location = NSMaxRange(foundRange); 
     if (searchRange.location >= self.length) 
      break; 
     searchRange.length = selfLength - searchRange.location; 
    } 

    return count; 
} 

Le Gist I lié ci-dessus donne quelques cas de test évidents.

+0

Merci, je vais essayer. –

1

NSRange n'est pas un objet, vous devez donc le mettre en un. Regardez NSValue s +valueWithRange: méthode de classe.

+0

Merci. Je peux me voir avoir des problèmes avec quelque chose comme ça, alors je garderai NSValue à l'esprit. Je crois que j'ai toujours le problème d'obtenir les NSRanges en premier lieu, bien que ... –