How to make the highlighted matches (NSRegularExpression)? - ios

I want to make the matches were blue in TextView.
NSString *text = #"Except as contained in #wep this notice, the name of a copyright #ololo holder shall not be used in #pewpewpew advertising or otherwise to #promote";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"#\\w*" options:0 error:NULL];
NSArray *matches = [regex matchesInString:text options:0 range:NSMakeRange(0, [text length])];
NSLog(#"count %d", matches.count);
for (NSTextCheckingResult *match in matches) {
NSRange matchRange = [match range];
NSString *match = [text substringWithRange:matchRange];
NSLog(#"Matched string: %#", match);
}
self.myTextView.text = text;

you have to create NSAttributedString and then apply font as per range and set attributedText to your UITextView not a simple text.
your code should look like below.
NSMutableAttributedString *attrib = [[NSMutableAttributedString alloc]initWithString:text];
for (NSTextCheckingResult *match in matches) {
NSRange matchRange = [match range];
NSString *match = [text substringWithRange:matchRange];
NSLog(#"Matched string: %#", match);
// set your rgb color here which you want i added blue color.
[attrib addAttribute:NSForegroundColorAttributeName
value:[UIColor blueColor]
range:matchRange];
}
// set attributed text not a normal text.
self.myTextView.attributedText = attrib;
Maybe this will help you.

self.myTextView.attributedText = // your attributed string here

Related

Remove hashtag from string after typing, store it in a different string

I am trying to create functionality where if the user typed in a hashtag it would remove it from the textview and store it in a string. This would be triggered by typing a hashtag and hitting space after it.
What's a good way to go about this?
I figured out how to get the word out thats hash tagged. Just need a way to remove it from my display. and leave the rest of the text.
NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:#"(#(\\w+))"
options:0
error:&error];
NSArray * matches = [regex matchesInString:stringCheck options:0 range:NSMakeRange(0, [stringCheck length])];
for (NSTextCheckingResult* match in matches ) {
NSRange wordRange = [match rangeAtIndex:1];
NSString* word = [stringCheck substringWithRange:wordRange];
NSLog(#"%#", word);
}
Is this what you're looking for?
set textView delegate to your .m and .h files
<UITextFieldDelegate> and [self.textField setDelegate:self];
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSLog(#"string: %#", string);
if ([string isEqualToString:#" "])
{
NSString *stringCheck = textField.text;
NSError *error;
NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:#"(#(\\w+))"
options:0
error:&error];
NSArray * matches = [regex matchesInString:stringCheck options:0 range:NSMakeRange(0, [stringCheck length])];
for (NSTextCheckingResult* match in matches ) {
NSRange wordRange = [match rangeAtIndex:1];
NSString* word = [stringCheck substringWithRange:wordRange];
NSLog(#"%#", word);
[self.textField setText:#""];
}
}
return YES;
}

How the find the all the ranges of all strings between quotation marks

I have been working on this problem for a couple of days but can't find a solution to it. I have a very long string that contains a lot of quotes and I want to be able to find all of the strings (the ranges of this strings) so that I can bold them using NSMutableAttributedString
Example
This is a string "with quoted" text and there is "some more" quoted text.
I want to be able to turn this string into the following:
This is a string "with quoted" text and there is "some more" quoted text.
This is what I have so far but it won't do the rest of the string:
- (void)stringBetweenString:(NSString*)start andString:(NSString*)end inString:(NSMutableAttributedString *)text
{
NSRange startRange = [[text string] rangeOfString:start];
if (startRange.location != NSNotFound)
{
NSRange targetRange;
targetRange.location = startRange.location + startRange.length;
targetRange.length = [text length] - targetRange.location;
NSRange endRange = [[text string] rangeOfString:end options:0 range:targetRange];
if (endRange.location != NSNotFound)
{
targetRange.length = endRange.location - targetRange.location;
[text addAttribute:NSFontAttributeName value:[NSFont fontWithName:#"Helvetica-Bold" size:12.0] range:targetRange];
}
}
}
If text is too long this could be little bit slow however it works. Working on Regex solution.
NSString *string = #"Example This is a string \"with quoted1\" text and there is \"some more1\" quoted text. I want to be able to turn this string into the following: This is a string \"with quoted2\" text and there is \"some more2\" quoted text.";
NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:string attributes:nil];
int leftFromLeft = 0;
while ([string rangeOfString:#"\""].location != NSNotFound) {
NSRange quoteLocationFirst = [string
rangeOfString:#"\""
options:0
range:NSMakeRange(leftFromLeft, string.length - leftFromLeft)
];
leftFromLeft = quoteLocationFirst.location + quoteLocationFirst.length;
NSRange quoteLocationSecond = [string
rangeOfString:#"\""
options:0
range:NSMakeRange(leftFromLeft, string.length - leftFromLeft)
];
NSRange quotedTextRange = NSMakeRange(
quoteLocationFirst.location,
quoteLocationSecond.location - quoteLocationFirst.location + 1
);
UIFont *font = [UIFont fontWithName:#"Helvetica-Bold" size:30.0f];
[attString addAttribute:NSFontAttributeName value:font range:quotedTextRange];
NSLog(#"%# \r\n\r\n", [string substringWithRange:quotedTextRange]);
leftFromLeft = quoteLocationSecond.location + quoteLocationSecond.length;
if ([string rangeOfString:#"\"" options:0 range:NSMakeRange(leftFromLeft, string.length - leftFromLeft)].location == NSNotFound) {
string = #"";
}
}
Edit
Regex solution appears to be better/faster.
NSString *string = #"Example This is a string \"with quoted1\" text and there is \"some more1\" quoted text. I want to be able to turn this string into the following: This is a string \"with quoted2\" text and there is \"some more2\" quoted text. Example This is a string \"with quoted3\" text and there is \"some more3\" quoted text. I want to be able to turn this string into the following: This is a string \"with quoted4\" text and there is \"some more4\" quoted text.";
NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:string attributes:nil];
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"\"([^\"]*)\"" options:NSRegularExpressionCaseInsensitive error:nil];
NSArray *arrayOfAllMatches = [regex matchesInString:string options:0 range:NSMakeRange(0, string.length)];
for (NSTextCheckingResult *match in arrayOfAllMatches) {
UIFont *font = [UIFont fontWithName:#"Helvetica-Bold" size:30.0f];
[attString addAttribute:NSFontAttributeName value:font range:match.range];
//NSLog(#"%#", [string substringWithRange:match.range]);
}

Detect underscore from a particular word of a UITextView's text

I want to detect "_" from a particular word of a UITextView's text.
I already tried this :
But this calculates the range of first underscore only.
NSMutableAttributedString *string = [[NSMutableAttributedString alloc]initWithString:textView.text];
NSRange range=[textView.text rangeOfString:#"_"];
[string addAttribute:NSForegroundColorAttributeName value:[UIColor clearColor] range:range];
textView.attributedText=string;
My output is coming like this
Tadeusz_Kościuszko was a military leader who became a national hero in
Poland. A poster for the Paris premiere of Jules_Massenet's 1910 opera
Don_Quichotte.
And I want something like this:
Tadeusz Kościuszko was a military leader who became a national hero in
Poland. A poster for the Paris premiere of Jules Massenet's 1910 opera
Don Quichotte.
Also I want to clear color the underscores just from the names. Not from the other text of UITextView.
I dont want to remove it from the whole text of UITextView but just from the particular words.
Anyone having suggestions?
Thanks.
textView.text = [textView.text stringByReplacingOccurrencesOfString:#"_" withString:#" "];
NSMutableAttributedString *string = [[NSMutableAttributedString alloc]initWithString:textView.text];
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"(_)" options:kNilOptions error:nil];
NSRange range = NSMakeRange(0,string.length);
[regex enumerateMatchesInString:string options:kNilOptions range:range usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
NSRange subStringRange = [result rangeAtIndex:1];
[string addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:subStringRange];
}];
textView.attributedText=string;
try this -
NSString *str = #"Tadeusz_Kościuszko was a military leader who became a national hero in Poland. A poster for the Paris premiere of Jules_Massenet's 1910 opera Don_Quichotte.";
NSString *newStr = [str stringByReplacingOccurrencesOfString:#"_" withString:#" "];
NSLog(#"NEW STR ::::: %#",newStr);
NSString *str = #"This_is_a_string";
str = [str stringByReplacingOccurrencesOfString:#"_"
withString:#" "];
// str = "This is a string"
More on NSString
Found the workaround :)
NSString *strTemp = textView.text;
NSMutableAttributedString *mutString = [[NSMutableAttributedString alloc]initWithString:strTemp];
NSString *substring = #"_";
NSRange searchRange = NSMakeRange(0,mutString.length);
NSRange wholeTextRange = [strTemp rangeOfString:strTemp];
[mutString addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:wholeTextRange];
NSRange foundRange;
while (searchRange.location < mutString.length)
{
searchRange.length = mutString.length-searchRange.location;
foundRange = [strTemp rangeOfString:substring options:nil range:searchRange];
if (foundRange.location != NSNotFound) {
// found an occurrence of the substring! do stuff here
[mutString addAttribute:NSForegroundColorAttributeName value:[UIColor clearColor] range:foundRange];
searchRange.location = foundRange.location+foundRange.length;
} else {
// no more substring to find
[txtComment setAttributedText:mutString];
break;
}
}
If you want to selectively remove underscores you need to know the range of text from which you want to remove them.
Then you can use a regular expression to get an array of ranges which match the underscore in that known range.
NSError *error;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"_" options:0 error:&error];
NSArray *matchingRangesInSelectedRange = [regex matchesInString:yourString options:0 range:knownRangeToCheckForMatches];
You can then iterate over the ranges in the array and do whatever changes you wish.
If you know which strings should not be cleaned or which that should not be cleaned you could do something like this:
NSString *stringWithUnderScore = #"A rather long text with some_odd_underscores but also names like André_Franquin & Albert_Uderzo";
NSSet *stringsThatShouldKeepUnderscore = [NSSet setWithObjects:#"some_odd_underscores", nil];
NSArray *singleStrings = [stringWithUnderScore componentsSeparatedByString:#" "];
NSMutableString *newCompleteString = [[NSMutableString alloc] init];
for (NSString *singleString in singleStrings) {
if (![stringsThatShouldKeepUnderscore containsObject:singleString]){
NSString *fixedString = [singleString stringByReplacingOccurrencesOfString:#"_" withString:#" "];
[newCompleteString appendString: fixedString];
} else{
[newCompleteString appendString:singleString];
}
[newCompleteString appendString:#" "];
}
NSLog(#"new string:%#",newCompleteString);
Edit: If you do not have this information you could try to make some kind of parser checking if each of the strings separated by "_" have capital-letters, indicating a name. Not fail-safe, but without knowledge about the text I can't really see any better option.

UILabel Bold / Highlight All occurrences SubString

I have multiple UILabels within a Custom Table cell. These labels contain varied text or varied length.
As it stands i have UILabel Subclassed allowing me to implement these methods
- (void)boldRange:(NSRange)range {
if (![self respondsToSelector:#selector(setAttributedText:)]) {
return;
}
NSMutableAttributedString *attributedText;
if (!self.attributedText) {
attributedText = [[NSMutableAttributedString alloc] initWithString:self.text];
} else {
attributedText = [[NSMutableAttributedString alloc]initWithAttributedString:self.attributedText];
}
[attributedText setAttributes:#{NSFontAttributeName:[UIFont boldSystemFontOfSize:self.font.pointSize]} range:range];
self.attributedText = attributedText;
NSLog(#"%#", NSStringFromRange(range));
}
- (void)boldSubstring:(NSString*)substring {
NSRange range = [self.text rangeOfString:substring];
[self boldRange:range];
}
This allows me to call [cell.StoryLabel boldSubstring:#"test"]; which will BOLD the first occurrence of the word 'test'.
What i am after is the ability to either create new subclass methods or extend the ones i already have, to allow me to replace ALL occurrences of a specified word within the label.
I have looked into a number of methods including 3rd party frameworks. The trouble i have is this is a learning process for me. I would be far more beneficial for me to try and complete this myself.
Thanks in advance!
rangeOfString returns the first occurrence, that's normal behavior.
From the Doc:
Finds and returns the range of the first occurrence of a given string
within the receiver.
You could use a NSRegularExpression, and use matchesInString:options:range to get a NSArray of NSTextCheckingResult (that have a NSRange property), an use a for loop to bold it.
This should do the trick:
- (void)boldSubstring:(NSString*)substring
{
if (![self respondsToSelector:#selector(setAttributedText:)])
{
return;
}
NSError *error;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern: substring options:NSRegularExpressionCaseInsensitive error:&error];
if (!error)
{
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:[self text]];
NSArray *allMatches = [regex matchesInString:[self text] options:0 range:NSMakeRange(0, [[self text] length])];
for (NSTextCheckingResult *aMatch in allMatches)
{
NSRange matchRange = [aMatch range];
[attributedString setAttributes:#{NSFontAttributeName:[UIFont boldSystemFontOfSize:self.font.pointSize]} range: matchRange];
}
[self setAttributedText:attributedString];
}
}

How to get NSRange(s) for a substring in NSString? [duplicate]

This question already has answers here:
How to get all NSRange of a particular character in a NSString?
(4 answers)
Closed 9 years ago.
NSString *str = #" My name is Mike, I live in California and I work in Texas. Weather in California is nice but in Texas is too hot...";
How can I loop through this NSString and get NSRange for each occurrence of "California", I want the NSRange because I would like to change it's color in the NSAttributed string.
NSRange range = NSMakeRange(0, _stringLength);
while(range.location != NSNotFound)
{
range = [[attString string] rangeOfString: #"California" options:0 range:range];
if(range.location != NSNotFound)
{
range = NSMakeRange(range.location + range.length, _stringLength - (range.location + range.length));
[attString addAttribute:NSForegroundColorAttributeName value:_green range:range];
}
}
Lots of ways of solving this problem - NSScanner was mentioned; rangeOfString:options:range etc. For completeness' sake, I'll mention NSRegularExpression. This also works:
NSMutableAttributedString *mutableString = nil;
NSString *sampleText = #"I live in California, blah blah blah California.";
mutableString = [[NSMutableAttributedString alloc] initWithString:sampleText];
NSString *pattern = #"(California)";
NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:nil];
// enumerate matches
NSRange range = NSMakeRange(0,[sampleText length]);
[expression enumerateMatchesInString:sampleText options:0 range:range usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
NSRange californiaRange = [result rangeAtIndex:0];
[mutableString addAttribute:NSForegroundColorAttributeName value:[NSColor greenColor] range:californiaRange];
}];
with
[str rangeOfString:#"California"]
and
[str rangeOfString:#"California" options:YOUR_OPTIONS range:rangeToSearch]
You may use rangeOfString:options:range: or NSScanner (there are other possibilities like regexps but anyway). It's easier to use first approach updating range, i.e. search for first occurrence and then depending on the result update the search range. When the search range is empty, you've found everything;

Resources