I would like to find all occurrences of a substring in a NSString, and iterate one by one to do some changes to that NSString. How should I do it?
Asked
Active
Viewed 4,942 times
6
-
Do you mean if you had `@"abcabcabcabcabcabc"` you want to iterate over all of the `@"abc"`s? – mattjgalloway Mar 08 '12 at 10:07
5 Answers
12
How about
// find first occurrence of search string in source string
NSRange range = [sourceString rangeOfString:@"searchString"];
while(range.location != NSNotFound)
{
// build a new string with your changed values
range = [sourceString rangeOfString:@"searchString" options:0 range:NSMakeRange(range.location + 1, [sourceString length] - range.location - 1)];
}
Or just
[sourceString stringByReplacingOccurrencesOfString:searchString withString:targetString];
if you want to change the searchString to the same value everywhere in the source string.

brynbodayle
- 6,546
- 2
- 33
- 49

TheEye
- 9,280
- 2
- 42
- 58
-
Also using: NSArray *stringArray = [myString componentsSeparatedByString:@"mySubString"]; – Luis Andrés García Mar 08 '12 at 10:16
-
-
2By componentsSeparated... you remove all the occurrences of your search string, you do not iterate over them ... – TheEye Mar 08 '12 at 10:21
7
I would go with something like this:
// Setup what you're searching and what you want to find
NSString *string = @"abcabcabcabc";
NSString *toFind = @"abc";
// Initialise the searching range to the whole string
NSRange searchRange = NSMakeRange(0, [string length]);
do {
// Search for next occurrence
NSRange range = [string rangeOfString:toFind options:0 range:searchRange];
if (range.location != NSNotFound) {
// If found, range contains the range of the current iteration
// NOW DO SOMETHING WITH THE STRING / RANGE
// Reset search range for next attempt to start after the current found range
searchRange.location = range.location + range.length;
searchRange.length = [string length] - searchRange.location;
} else {
// If we didn't find it, we have no more occurrences
break;
}
} while (1);

mattjgalloway
- 34,792
- 12
- 100
- 110
-
that's way to complicated, there's a method for that: `- (void)enumerateSubstringsInRange:(NSRange)range options:(NSStringEnumerationOptions)opts usingBlock:(void (^)(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop))block`. – calimarkus Mar 08 '12 at 10:40
-
-
Matt's method allows you to change the string, as it's not being enumerated, tho. – Stephen J Apr 05 '17 at 18:44
5
If you want to do changes, you could use:
- (NSString *)stringByReplacingOccurrencesOfString:(NSString *)target withString:(NSString *)replacement
but if that doesn't fit your needs try this:
- (void)enumerateSubstringsInRange:(NSRange)range options:(NSStringEnumerationOptions)opts usingBlock:(void (^)(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop))block

calimarkus
- 9,955
- 2
- 28
- 48
1
You might want to have a look on NSString class Documentation.
Finding Characters and Substrings
– rangeOfCharacterFromSet:
– rangeOfCharacterFromSet:options:
– rangeOfCharacterFromSet:options:range:
– rangeOfString:
– rangeOfString:options:
– rangeOfString:options:range:
– rangeOfString:options:range:locale:
– enumerateLinesUsingBlock:
– enumerateSubstringsInRange:options:usingBlock:
Dividing Strings
– componentsSeparatedByString:
– componentsSeparatedByCharactersInSet:
– stringByTrimmingCharactersInSet:
– substringFromIndex:
– substringWithRange:
– substringToIndex:

HelmiB
- 12,303
- 5
- 41
- 68
0
Expanding on @TheEye's answer, I cooked this up:
@interface NSString (EnumerateOccurancesOfString)
- (void)enumerateOccurancesOfString:(NSString *)string usingBlock:(void (^)(NSRange substringRange, BOOL *stop))block;
@end
-
@implementation NSString (EnumerateOccurancesOfString)
- (void)enumerateOccurancesOfString:(NSString *)string usingBlock:(void (^)(NSRange range, BOOL * _Nonnull stop))block {
NSParameterAssert(block);
NSRange range = [self localizedStandardRangeOfString:string];
if (range.location == NSNotFound) return;
// Iterate all occurances of 'string'
while (range.location != NSNotFound)
{
BOOL stop = NO;
block(range, &stop);
if (stop) {
break;
}
// Continue the iteration
NSRange nextRange = NSMakeRange(range.location + 1, self.length - range.location - 1);
range = [self rangeOfString:string options:(NSStringCompareOptions)0 range:nextRange locale:[NSLocale currentLocale]]; // Will this sometimes conflict with the initial range obtained with -localizedStandardRangeOfString:?
}
}
@end

Community
- 1
- 1

Stian Høiland
- 3,625
- 2
- 27
- 32