Working with regular expressions in iOS 10Hello! In this article we will discuss how to work with NSRegularExpression and NSDataDetector,
all those who are not indifferent are invited under cat.

A regular expression is a string or sequence of characters that define a pattern. With which you can make very flexible search samples in the text.
')
Suppose we have some text in a line and our task is to find all the listed email addresses in it. The best tool for this task is regular expressions.
Writing R.V. (Regular Expression) for checking email. First you need to describe the basic conditions of all possible combinations of types of email addresses. In the most minimal version, it can be the following: a@b.io
- from 1 character to the box name - up to 64 characters
- from 1 reserved dog symbol
- from 1 character of resource name - up to 64 characters
- from 2 characters of the domain - up to 64 characters
We start to make RVs in stages:
@ "
([a-z0-9]) "
- says that the name of the box can contain any letter and any number
@ "([a-z0-9])
{1.64} "
- says that a group of these characters can be from 1 to 64 characters long
@ "([a-z0-9
! # $% & '* + - / =? ^ _` {|} ~ ]) {1.64} "
- says that you can also specify these characters
@ "([a-z0-9! # $% & '* + - / =? ^ _` {|} ~]) {1.64}
@ "
- says that the dog at this place is required
@ "([a-z0-9! # $% & '* + - / =? ^ _` {|} ~]) {1.64} @
([a-z0-9! # $% &' * + - / =? ^ _ `{|} ~]) {1.64}"
- Add all the same characters, only after @
@ "([a-z0-9! # $% & '* + - / =? ^ _` {|} ~]) {1.64} @ ([a-z0-9! # $% &' * + - / =? ^ _ `{|} ~]) {1.64}
\\. "
- says that the dot character on this place is required
@ "([a-z0-9! # $% & '* + - / =? ^ _` {|} ~]) {1.64} @ ([a-z0-9! # $% &' * + - / =? ^ _ `{|} ~]) {1.64} \\.
([A-z0-9]) {2.64} "
- says that the domain name can contain letters and numbers of the total amount of characters from 2 to 64 characters

We just made a full-fledged regular expression.
Incomplete reference book of reserved characters for PB:
Symbol | Value |
---|
^ | beginning of the line to be checked |
$ | end of line to be checked |
. | any character |
| | logical OR |
? | preceding character or group of characters is optional |
+ | one or more instances of the previous item |
* | any number of instances of the item (including zero |
\ d | numeric character |
\ D | not numbers symbol |
\ s | whitespace |
\ S | not white space |
\ w | matches any letter or number; equivalent of [a-zA-Z0-9_] |
\ W | on the contrary, the equivalent of [^ a-zA-Z0-9_], all characters except these |
Quantifiers | |
---|
{n} | exactly n times |
{m, n} | inclusive M to N |
{m,} | at least m times |
{, n} | no more than n times |
() | group creation |
[] | in such brackets we say, "any character of these, but only one |
Creating NSRegularExpression
self.mainText = @"There's also +39(081)-552-1488 a “Bookmark” button that allows the user to highlight any date, time or location in the text. For simplicity's sake, www.ok.ru you won't +39(081)552 2080 not cover every possible format of date, time and 2693485 location strings that can appear in your text. You'll implement the https://github.com bookmarking functionality +249-54-85 at the very end +39 333 3333333 of the tutorial. vk.com Your first step to getting the search functionality working is to turn standard strings representing regular expressions into http://app.com NSRegularExpression objects."; NSString* pattern = @"\\b(in)|(or)\\b";
For the sake of justice, I should note that when creating a pattern, we must write in the string not easy \ w, (or any other letter or symbol that is reserved)
and write backslash twice to escape NSString. \\ w
NSRegularExpression instance manipulation
Total number of all matches found NSUInteger numberOfMatches = [regex numberOfMatchesInString:_mainText options:0 range:NSMakeRange(0, [_mainText length])];
Returns the range of the first match. NSRange rangeOfFirstMatch = [regex rangeOfFirstMatchInString:_mainText options:0 range:NSMakeRange(0, [_mainText length])]; if (!NSEqualRanges(rangeOfFirstMatch, NSMakeRange(NSNotFound, 0))) { NSString *substringForFirstMatch = [_mainText substringWithRange:rangeOfFirstMatch]; }
Get an array of all matches found. NSArray *matches = [regex matchesInString:_mainText options:0 range:NSMakeRange(0, [_mainText length])]; for (NSTextCheckingResult *match in matches) {
We get the first match of the total NSTextCheckingResult *match = [regex firstMatchInString:_mainText options:0 range:NSMakeRange(0, [_mainText length])]; if (match) { NSRange matchRange = [match range]; NSRange firstHalfRange = [match rangeAtIndex:1]; NSRange secondHalfRange = [match rangeAtIndex:2]; }
We iterate through the block for each match __block NSUInteger count = 0; [regex enumerateMatchesInString:_mainText options:0 range:NSMakeRange(0, [_mainText length]) usingBlock:^(NSTextCheckingResult *match, NSMatchingFlags flags, BOOL *stop){ NSRange matchRange = [match range]; NSRange firstHalfRange = [match rangeAtIndex:1]; NSRange secondHalfRange = [match rangeAtIndex:2]; if (++count >= 100) *stop = YES; }];
Finding our pattern in the text and insert the word Sieg in its place !!! NSString *modifiedString = [regex stringByReplacingMatchesInString:_mainText options:0 range:NSMakeRange(0, [_mainText length]) withTemplate:@"Sieg!!!"];
NSDataDetector class overview
NSDataDetector is a subclass of
NSRegularExpression , made for easy searching (links, phone numbers, dates, etc.). That is, this actual class under its hood contains universal regular expressions for finding the above.
Also, the NSDataDetector can call all
NSRegularExpression methods, also look for firstMatch / matches for all text, etc.
Manipulating the NSDataDetector instance
Creating an instance of NSDataDectector NSError* error1 = nil; NSDataDetector* detector=[NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink | NSTextCheckingTypePhoneNumber error:&error];
Number of matches found in the text NSUInteger numberOfMatchesFromDetect = [detector numberOfMatchesInString:_mainText options:0 range:NSMakeRange(0,[_mainText length])];
All matches in one array (it contains NSTextCheckingResult objects) NSArray* matchesFromDetect =[detector matchesInString:_mainText options:0 range:NSMakeRange(0,[_mainText length])];
We pass a block on all matches __block NSUInteger countForDectect = 0; [detector enumerateMatchesInString:_mainText options:0 range:NSMakeRange(0, [_mainText length]) usingBlock:^(NSTextCheckingResult * _Nullable result, NSMatchingFlags flags, BOOL * _Nonnull stop) { NSRange matchRange = result.range; NSLog(@"In Enumerate = %d, \tRange = %@\t \tText = %@",countForDectect, NSStringFromRange(matchRange), [_mainText substringWithRange:matchRange]); countForDectect++; }];
Brief documentation of propertiesProperty instance NSRegularExpression | Treatment |
---|
var pattern: String | Returns a regular expression pattern. |
var options: NSRegularExpression.Options | Returns the search parameters for example: look for case insensitive NSRegularExpressionCaseInsensitive. |
var numberOfCaptureGroups: int | Returns the number of groups from the regular expression pattern, for example: @ »^ (ab | bc) (amg | img) $" - here are two groups |
Everyone who read to the end and put a thumbs up, I will be very grateful.
The project can be found at this link:
here