Проблема с использованием NSRange: индекс выходит за пределы

Я пытаюсь обнаружить URL-адрес веб-сайта в своей строке, а затем делаю некоторые строки атрибуции, такие как выделение жирным шрифтом и т. Д.

Мое регулярное выражение определяется как:

static NSRegularExpression *websiteRegularExpression;
static inline NSRegularExpression * WebsiteRegularExpression() {
    if (!websiteRegularExpression) {
        websiteRegularExpression = [[NSRegularExpression alloc] initWithPattern:@"\b(https?|ftp|file)://[-A-Z0-9+&@#/%?=~_|!:,.;]*[A-Z0-9+&@#/%=~_|]" 
                                                                        options:NSRegularExpressionCaseInsensitive 
                                                                          error:nil];
    }

    return websiteRegularExpression;
}

Вот где я перечисляю:

 -(void)setBodyText
    {
        __block NSRegularExpression *regexp = nil;    
        bodyLabel.delegate = self;
        [self.bodyLabel setText:@"http://www.google.com" afterInheritingLabelAttributesAndConfiguringWithBlock:^NSAttributedString *(NSMutableAttributedString *mutableAttributedString) {

            NSRange stringRange = NSMakeRange(0, [mutableAttributedString length]);

            regexp = WebsiteRegularExpression ();
            NSRange nameRange = [regexp rangeOfFirstMatchInString:[mutableAttributedString string] options:0 range:stringRange];
            UIFont *boldSystemFont = [UIFont boldSystemFontOfSize:18.0]; 
            CTFontRef boldFont = CTFontCreateWithName((CFStringRef)boldSystemFont.fontName, boldSystemFont.pointSize, NULL);
            if (boldFont) {
                [mutableAttributedString addAttribute:(NSString *)kCTFontAttributeName value:(id)boldFont range:nameRange];
                CFRelease(boldFont);
            }

            [mutableAttributedString replaceCharactersInRange:nameRange withString:[[[mutableAttributedString string] substringWithRange:nameRange] uppercaseString]];
            return mutableAttributedString;
        }];

        regexp = WebsiteRegularExpression();
        NSRange linkRange = [regexp rangeOfFirstMatchInString:self.bodyLabel.text options:0 range:NSMakeRange(0, [bodyLabel.text length])];
        [self.bodyLabel addLinkToURL:nil withRange:linkRange];
    }

Я получаю сообщение об ошибке:

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSCFString substringWithRange:]: Range or index out of bounds'

Как я могу решить?


person Sheehan Alam    schedule 29.06.2011    source источник
comment
Вы можете опубликовать регулярные выражения, которые вы используете? в частности, что такое mutableAttributedString. я думаю, что-то не так в этой строке. [mutableAttributedString replaceCharactersInRange:nameRange withString:[[[строка mutableAttributedString] substringWithRange:nameRange] uppercaseString]]; вы можете отладить его, убедившись, что каждый шаг дает то, что вы ожидали.   -  person madmik3    schedule 29.06.2011
comment
Я считаю, что вы правы. Я обновил свой код с помощью регулярного выражения. До сих пор не знаю, как решить...   -  person Sheehan Alam    schedule 29.06.2011


Ответы (2)


Проверьте содержимое nameRange, прежде чем вызывать substringWithRange. Если ваше регулярное выражение не соответствует, возвращаемое значение для rangeOfFirstMatchInString будет

{NSNotFound, 0}

NSNotFound определяется как NSIntegerMax, так что вы можете себе представить, почему это значение может быть вне допустимого диапазона для вашей mutableAttributedString.

Обновление для комментария

Итак, чтобы проверить результаты substringWithRange:

if (nameRange.location == NSNotFound)
    // didn't match the WebsiteRegularExpression() do something else
person RedBlueThing    schedule 29.06.2011
comment
как я могу проверить содержимое nameRange? - person Sheehan Alam; 29.06.2011
comment
@sheehan-alam просто проверьте элемент местоположения в объекте диапазона (см. Обновление). - person RedBlueThing; 29.06.2011

Нигде вы не проверяете, имеет ли какой-либо диапазон, который вы вернули, range.location = NSNotFound. Одна из ваших спичек оказывается пустой, а затем вы пытаетесь использовать диапазон для других целей.

person Kendall Helmstetter Gelner    schedule 29.06.2011
comment
Я новичок в NSRange, можете ли вы показать мне пример того, как я могу выполнить эту проверку в своем коде? - person Sheehan Alam; 29.06.2011
comment
Поскольку RedBlue опередил меня в ответе, я просто проголосовал за его ответ. - person Kendall Helmstetter Gelner; 29.06.2011