Search for words using brackets placed around them in iOS

I am trying to find all the words with brackets around them in a group of text and change it to italics in iOS. I use this code to find brackets in the text:

static inline NSRegularExpression * ParenthesisRegularExpression() { static NSRegularExpression *_parenthesisRegularExpression = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _parenthesisRegularExpression = [[NSRegularExpression alloc] initWithPattern:@"\\[[^\\(\\)]+\\]" options:NSRegularExpressionCaseInsensitive error:nil]; }); return _parenthesisRegularExpression; } 

I use this to show me matches:

 NSRange matchRange = [result rangeAtIndex:0]; NSString *matchString = [[self.markerPointInfoDictionary objectForKey:@"long_description"] substringWithRange:matchRange]; NSLog(@"%@", matchString); 

But he returns me all the text from the first [to the last] in the group of text. Between them there are many brackets.

I use this code to change the text to italics:

 -(TTTAttributedLabel*)setItalicTextForLabel:(TTTAttributedLabel*)attributedLabel fontSize:(float)Size { [attributedLabel setText:[self.markerPointInfoDictionary objectForKey:@"long_description"] afterInheritingLabelAttributesAndConfiguringWithBlock:^NSMutableAttributedString *(NSMutableAttributedString *mutableAttributedString) { NSRange stringRange = NSMakeRange(0, [mutableAttributedString length]); NSRegularExpression *regexp = ParenthesisRegularExpression(); UIFont *italicSystemFont = [UIFont italicSystemFontOfSize:Size]; CTFontRef italicFont = CTFontCreateWithName((__bridge CFStringRef)italicSystemFont.fontName, italicSystemFont.pointSize, NULL); [regexp enumerateMatchesInString:[mutableAttributedString string] options:0 range:stringRange usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { NSRange matchRange = [result rangeAtIndex:0]; NSString *matchString = [[self.markerPointInfoDictionary objectForKey:@"long_description"] substringWithRange:matchRange]; NSLog(@"%@", matchString); if (italicFont) { [mutableAttributedString removeAttribute:(NSString *)kCTFontAttributeName range:result.range]; [mutableAttributedString addAttribute:(NSString *)kCTFontAttributeName value:(__bridge id)italicFont range:result.range]; CFRelease(italicFont); NSRange range1 = NSMakeRange (result.range.location, 1); NSRange range2 = NSMakeRange (result.range.location + result.range.length -2 , 1); [mutableAttributedString replaceCharactersInRange:range1 withString:@""]; [mutableAttributedString replaceCharactersInRange:range2 withString:@""]; } }]; return mutableAttributedString; }]; return attributedLabel; } 

Btw my Text looks like this:

 [hello] welcome [world], my [name] is [lakesh] 

The results look like this:

 match string is [hello] match string is [world] match string is  is [lak then crash.. 

Need to be guided to show me my mistake.

+4
source share
2 answers

I did not think about the code you are showing, but your regex seems too greedy:

 @"\\[[^\\(\\)]+\\]" 

This corresponds to the 1-character value between the brackets "[]". Characters are defined by a character class that says "all characters except paranthesis", i.e. Besides "()".

In other words, your character class also matches parenthesized characters. The result is that your expression matches everything that is between the first "[" and "last"].

I suggest you try the following regular expression:

 @"\\[[^\\[\\]]+\\]" 

If you don't have nested brackets, you can even simplify this:

 @"\\[[^\\]]+\\]" 

<h / "> EDIT

This is a simplified version of your code and the introductory text of the example you provided, but using the regular expression that I suggested. In my environment, this works fine, it outputs 4 lines to the debug output window. I don’t know what causes your failure, so I suggest that you gradually simplify your own code until you find the problem.

 NSString* mutableAttributedString = @"[hello] welcome [world], my [name] is [lakesh]"; NSRange stringRange = NSMakeRange(0, [mutableAttributedString length]); NSRegularExpression* regexp = [[NSRegularExpression alloc] initWithPattern:@"\\[[^\\]]+\\]" options:NSRegularExpressionCaseInsensitive error:nil]; [regexp enumerateMatchesInString:mutableAttributedString options:0 range:stringRange usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) { NSRange matchRange = [result rangeAtIndex:0]; NSString* matchString = [mutableAttributedString substringWithRange:matchRange]; NSLog(@"%@", matchString); } ]; 

The main differences from your code:

  • I do not work with TTTAttributedLabel
  • I do not use NSMutableAttributedString
  • I do not use self.markerPointInfoDictionary
  • I have no if (italicFont) code block

So your problem should be in one of these areas.

+7
source

What is your crash log? Do you change the string in place with ranges of matches from the original unchanged string? If so, you will finish the borders before graduation.

You can consider several approaches. You need to do the deletion one at a time and stop trying to make your code in italics and replace the character in the same place. It bothers you.

Your italics are fine. But you need to make the removal of your character an extra bit of iteration logic, which gets a new range of matches from the shorter line after each character.

+1
source

Source: https://habr.com/ru/post/1483543/


All Articles