3

I am trying to detect website URL's in my string and then doing some attribution string stuff like bolding it etc.

My regex is defined as:

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

Here is where I enumerate:

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

I get the error:

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

How can I resolve?

Sheehan Alam
  • 60,111
  • 124
  • 355
  • 556
  • can you post the regular expressions you are using? specifically what is mutableAttributedString. my guess is something is wrong in this line. [mutableAttributedString replaceCharactersInRange:nameRange withString:[[[mutableAttributedString string] substringWithRange:nameRange] uppercaseString]]; you might want to debug it by making sure each step is giving you want you expected. – madmik3 Jun 29 '11 at 03:08
  • I believe you are correct. I've updated my code with the regex. Still not sure how to resolve... – Sheehan Alam Jun 29 '11 at 03:31

2 Answers2

10

Check the contents of nameRange before you call substringWithRange. If your regular expression doesn't match then the return value for rangeOfFirstMatchInString will be

{NSNotFound, 0}

NSNotFound is defined as NSIntegerMax so you can imagine why this value might be out of range for your mutableAttributedString.

Update for comment

So to check the results of substringWithRange:

if (nameRange.location == NSNotFound)
    // didn't match the WebsiteRegularExpression() do something else
RedBlueThing
  • 42,006
  • 17
  • 96
  • 122
4

Nowhere are you checking to see if any range you got back has the range.location = NSNotFound. One of your matches is coming up empty and then you are trying to use the range for other things.

Lily Ballard
  • 182,031
  • 33
  • 381
  • 347
Kendall Helmstetter Gelner
  • 74,769
  • 26
  • 128
  • 150