amirfl
amirfl

Reputation: 1644

App crashes when capturing regex iOS

I'm trying to capture a wind description from a METAR weather report (downloaded from http://weather.noaa.gov/pub/data/observations/metar/cycles/) and get the components of the wind from that block if it matches. The regular expression is @"^([0-9]{3}|VRB)([0-9]{2,3})G?([0-9]{2,3})?(KT|MPS|KMH)".

I'm using the PDRegex library for enumerating the captured matches into an array. (The PDRegex library can be found on https://github.com/carlbrown/RegexOnNSString/blob/master/RegexOnNSString/NSString%2BPDRegex.m)

These are the applicable lines in my code:

word = @"16008KT"; //test block
NSArray *matches = [word stringsByExtractingGroupsUsingRegexPattern:@"^([0-9]{3}|VRB)([0-9]{2,3})G?([0-9]{2,3})?(KT|MPS|KMH)"];

When stringsByExtractingGroupsUsingRegexPattern (a PDRegex method) is called and matches, it crashes at line 62 of NSString+PDRegex. This is the line of PDRegex where the app crashes:

NSString *matchedString=[self substringWithRange:[result rangeAtIndex:i]];

And this is the crash report:

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

Upvotes: 0

Views: 889

Answers (3)

Alan Moore
Alan Moore

Reputation: 75222

It's probably because of the anchor (^). You're telling it to match the pattern only if it's at the beginning of the line. (Or at the beginning of the whole string if it's not in multiline mode, but it looks like multiline mode is the default.)

If you want to make sure you're matching a real wind description and not a part of some longer string that happens to look like one (e.g. foo12307KTbar), you can surround it with word boundaries:

\b([0-9]{3}|VRB)([0-9]{2,3})G?([0-9]{2,3})?(KT|MPS|KMH)\b

In Objective-C string literal form, I believe that would be:

@"\\b([0-9]{3}|VRB)([0-9]{2,3})G?([0-9]{2,3})?(KT|MPS|KMH)\\b"

Upvotes: 1

amirfl
amirfl

Reputation: 1644

I solved the problem by adding the following check above the problematic line:

if ([result rangeAtIndex:i].length!=0)

The problem occured because not all string parts in parentheses were matched, those unmatched ranges were out of range of the original 'word' string.

Upvotes: 2

Omar Freewan
Omar Freewan

Reputation: 2678

It seems your calling the range of out index, so make sure that the index i in the
NSString *matchedString=[self substringWithRange:[result rangeAtIndex:i]]; is defined

Upvotes: 1

Related Questions