In Objective-C, many of the NSString or NSMutableString methods for comparing or manipulating strings require a range argument--that is, an argument of data type NSRange
(a struct containing a starting position and a length). This applies outside of NSString (NSArray for example), but NSString is where I see it most frequently.
There does exist a convenience function for creating an NSRange struct:
NSRange range = NSMakeRange(position, length);
But the problem for me happens when I'm manipulating a string. I'll sometimes write a method in which I will make several different manipulations on the string within the same method. And the range I need to cover will be the entire length of the string. It's not acceptable to simply declare an NSRange
variable, set it, and use this throughout, because if the length of the string changes, the previously set range will be incorrect.
For example, suppose we're working with strings representing file paths. We want to manipulate the string in a few ways to make sure the path looks how we want it to look:
- (NSString *)cleanPath:(NSString *)originalPath inRoot:(NSString *)rootPath {
NSString *returnPath = [originalPath stringByReplacingOccurrencesOfString:@" " withString:@"" options:NSCaseInsensitiveCompare:NSMakeRange(0,[originalPath length])];
while ([returnPath rangeOfString:@"./"].location != NSNotFound) {
returnPath = [returnPath stringByReplacingOccurrencesOfString:@"./" withString:@"/" options:NSCaseInsensitiveCompare:NSMakeRange(0,[returnPath length])];
}
if ([returnPath rangeOfString:rootPath options:NSCaseInsensitiveCompare range:NSMakeRange(0,[returnPath length])] != NSNotFound) {
return returnPath;
} else {
return rootPath;
}
}
As you can see, we have three calls to NSMakeRange
just to make a range that encompasses the length of the string we're working on. We want to look at the whole range. Giving a range too short will mean we're not looking at every character, and giving a range too long will result in an out of bounds exception. We also can't know what the range will be.
We know that the first range will be the longest range, because we're only removing characters.
Also, even though the call only shows up in code once in the while loop, it could be called any number of times in actuality, so we can't even preset a range before the loop and use that number every time.
The other annoying thing is that NSMakeRange(0,[myString length])
doesn't offer a ton of autocomplete help.
I also don't want to simply #define
a macro that could accidentally have unintended consequences outside of this method.
What are my options to clean this up?
This is tagged C because even though the code here is Objective-C, NSRange is a C-style struct and NSMakeRange is a C-style function. Any C techniques for cleaning up something like this will definitely apply here.