Есть ли способ получить NSArray из NSRanges для появления строки NSString внутри другой строки NSString? - PullRequest
1 голос
/ 05 сентября 2010

Недавно я работал над простой в использовании системой подсветки синтаксиса для личного проекта. До сих пор у меня все работало правильно, находя диапазон определенных строк и выделяя этот диапазон в NSTextView. Все работает, пока вы не попытаетесь набрать выделенное слово дважды, что приводит к ошибке, показанной ниже:

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

Я считаю, что это происходит, потому что я получаю только первое вхождение строки NSString с помощью метода rangeOfString, и по этой причине подсвечивается только первый выделенный элемент.

Извините за длинное объяснение! В любом случае, мне было интересно, существует ли метод rangeOfString или что-то подобное, что может дать мне NSArray из NSRanges для каждого вхождения строки NSString внутри другой строки NSString. Ниже приведена строка кода, которую я использую для получения моего диапазона:

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];

Что бы я хотел, это примерно так:

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
}

Если это невозможно, может кто-нибудь указать мне правильное направление или предложить альтернативный способ подсветки синтаксиса? Спасибо!

Ответы [ 2 ]

3 голосов
/ 05 сентября 2010

Нет такого метода.Вы можете использовать rangeOfSubstring:options:range: для получения каждого соответствия и сужать диапазон по мере продвижения: после каждого соответствия вы меняете местоположение диапазона поиска на символ после (местоположение + длина) диапазона соответствия и уменьшаете длину диапазона поиска наразница.


В современном мире, основанном на блоках, не так сложно написать метод «перечисления подстрок, которые соответствуют…» , который выполняет вышеприведенное в качестве своей реализации.Вот как это выглядит:

- (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;
}

Gist, который я привел выше, дает несколько очевидных тестовых случаев.

1 голос
/ 05 сентября 2010

NSRange не является объектом, поэтому вам нужно поместить его в один.Посмотрите на NSValue s +valueWithRange: метод класса.

...