@vadian and @robmayoff have both provided good solutions based on regular expressions (REs), in both cases the REs are used to match the gaps to find where to break your string. For comparison approaching the problem the other way by using a RE to match the parts you are interested in is also possible. The RE:
\S+(\h\S+)*
will match the text you are interested in, made up as as follows:
\S - match any non-space character, \S excludes both horizontal
(e.g. spaces, tabs) and vertical space (e.g. newlines)
\S+ - one or more non-space characters, i.e. a "word" of sorts
\h - a single horizontal space character (if you wish matches to
span lines use \s - any horizontal *or* vertical space)
\h\S+ - a space followed by a word
(\h\S+)* - zero or more space separated words
\S+(\h\S+)* - a word follow by zero or more words
With this simple regular expression you can use matchesInString:options:range:
to obtain an array of NSTextCheckingResult
objects, one for each match in your input; or you can use enumerateMatchesInString:options:range:usingBlock:
to have a block called with each match.
As an example here is a solution following @robmayoff's approach:
@interface NSString (componentsMatchingRegularExpression)
- (NSArray<NSString *>*) componentsMatchingRegularExpression:(NSString *)pattern;
@end
@implementation NSString (componentsMatchingRegularExpression)
- (NSArray<NSString *>*) componentsMatchingRegularExpression:(NSString *)pattern
{
NSError *errorReturn;
NSRegularExpression *regularExpression = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:&errorReturn];
if (!regularExpression)
return nil;
NSMutableArray *matches = NSMutableArray.new;
[regularExpression enumerateMatchesInString:self
options:0
range:NSMakeRange(0, self.length)
usingBlock:^(NSTextCheckingResult * _Nullable result, NSMatchingFlags flags, BOOL * _Nonnull stop)
{
[matches addObject:[self substringWithRange:result.range]];
}
];
return matches.copy; // non-mutable copy
}
@end
Whether matching what you wish to keep or remove is better is subjective, take your pick.