iOS -- Strings -- Insert String at Specific Position - ios

I have a long string. I'd like to take this long string, search for any occurrences of words that appear between quotes (i.e., "string"), and insert a string before the word (i.e., "x"), and a string after the word (i.e., "y").
Any solutions would be most appreciated! Thanks!
I see that I could use the following to grab the text between the quotes:
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"([\"])
(?:\\\\\\1|.)*?\\1" options:0 error:&error];
NSRange range = [regex rangeOfFirstMatchInString:myString options:0 range:NSRangeMake(0,
[myString length]];
However, now I need to replace the text that is inside the quotations, inserting the html tags "bold" before and "/bold" after. Is there anyway for me to do this? Also, if there are multiple occurrences of quoted text in a given string, how would I use the above code to cycle through the string to get modify each piece of quoted text one-by-one?
I came across this post ([click here]]1 but I'm not quite sure how to modify the sample code to achieve the result I want. Any help would be great!

I will refer you to this page: Shortcuts in Objective-C to concatenate NSStrings
The page talks about adding strings together by using two NSMutable strings and adding one to both, which seems to be the preferable of the two it gives. Unfortunately, there is no operation to add two or more strings together (which really sucks).

Try this:
NSString *original=#"The quick 'brown fox' The quick 'brown fox' ";
NSString *target=[original stringByReplacingOccurrencesOfString:#"'brown fox'" withString:#"<b>brown fox</b>"];

Related

Checking if a given character is an emoji in Objective-C

I have an NSString and would like to check if a given character at a certain index is an emoji.
However, there doesn't seem to be any reliable way to create an NSCharacterSet of emoji characters, since they change from iOS update to update. And a lot of the available solutions rely on Swift features such as UnicodeScalar. All solutions seem to involve hardcoding the codepoint values for emojis.
As such, is it possible to check for emojis at all?
It's a bit of a complicated question because Unicode is complicated, but you can use NSRegularExpression to do this:
NSString *s = #"where's the emoji 😎 ?";
NSRegularExpression *r = [NSRegularExpression regularExpressionWithPattern:#"\\p{Emoji_Presentation}" options:0 error:NULL];
NSRange range = [r rangeOfFirstMatchInString:s options:0 range:NSMakeRange(0, s.length)];
NSLog(#"location %lu length %lu", (unsigned long)range.location, (unsigned long)range.length);
produces:
2019-01-16 18:07:42.629 emoji[50405:6837084] location 18 length 2
I'm using the \p{Unicode property name} pattern to match characters which have the specified Unicode property. I'm using the property Emoji_Presentation to get those character which present as Emoji by default. You should review Unicode® Technical Standard #51 — Annex A: Emoji Properties and Data Files and the data files linked in A.1 to decide which property you actually care about.

Using capture groups within an NSRegularExpression pattern

Is a regex of the following form legit in Obj C?
"<(img|a|div).*?>.*?</$1>"
I know it's valid in JS with a \1 instead of $1, but I'm having little luck in Obj C.
NSRegularExpression uses ICU Regular Expressions which uses \n syntax for back references where n is the nth capture group.
<(img|a|div).*?>.*?</\\1>
Yes, I do believe you can work with capture groups. I had to work with them a bit a little while ago and I have an example in:
-(NSString *) extractMediaLink:(NSString *)link withRegex:(NSString *)regex{
NSString * utf8Link = [link stringByRemovingPercentEncoding];
NSError * regexError = nil;
NSRegularExpression * regexParser = [NSRegularExpression regularExpressionWithPattern:regex
options:NSRegularExpressionCaseInsensitive|NSRegularExpressionUseUnixLineSeparators
error:&regexError];
NSTextCheckingResult * regexResults = [regexParser firstMatchInString:utf8Link
options:0
range:NSMakeRange(0, [utf8Link length])];
NSString * matchedResults = [utf8Link substringWithRange:[regexResults rangeAtIndex:1]]; // the second capture group will always have the ID
return matchedResults.length ? matchedResults : #"";
}
When you use an instance of NSRegularExpression to generate an NSTextCheckingResult, the NSTextCheckingResult has a property of numberOfRanges which is documented with:
A result must have at least one range, but may optionally have more (for example, to represent regular expression capture groups).
In my example above (Note: I happen to be parsing HTML, but using an addition pod that traverses HTML by XPath queries, TFHpple -- a lifesaver if you absolutely have to parse HTML), I use the -[NSRegularExpression firstMatchInString:options:range:] to check for the first instance of the tag that matches my regex pattern. From that NSTextCheckingResult I pull out the proper index of the capture group I'm interested in (in this case, [regexResults rangeAtIndex:1])
But, getting to this point was a huge pain in the ass. But to make sure you're getting the right expressions I would highly recommend using Regex101 with the Python setting, and then passing the refined regex into Patterns (Mac App Store)
If you want the full look, I have a fairly detailed project here, but keep in mind it's still a WIP.

NSString stringWithFormat not working with special chars like currency symbols

I have been having a lot of trouble with NSString's stringWithFormat: method as of late. I have written an object that allows you to align N lines of text (separated by new lines) either centered, right, or left. At the core of my logic is NSString's stringWithFormat. I use this function to pad my strings with spaces on the left or right of individual lines to produce the alignment I want. Here is an example:
NSString *str = #"$3.00" --> 3 dollars
[NSString stringWithFormat:#"%8s", [str cStringUsingEncoding:NSUnicodeStringEncoding]] --> returns --> " $3.00"
As you can see the above example works great, I padded 3 spaces on the left and the resulting text is right aligned/justified. Problems begin to arise when I start to pass in foreign currency symbols, the formatting just straight up does not work. It either adds extra symbols or just returns garbage.
NSString *str = #"Kč1.00" --> 3 Czech Koruna (Czech republic's currency)
[NSString stringWithFormat:#"%8s", [str cStringUsingEncoding:NSUnicodeStringEncoding]] --> returns --> " Kč1.00"
The above is just flat out wrong... Now I am not a string encoding expert but I do know NSString uses the international standardized unicode encoding for special characters well outside basic ASCII domain.
How can I fix my problem? What encoding should I use? I have tried so many different encoding enums I have lost count, everything from NSMACOSRomanEncoding to NSUTF32UnicodeBigEndian.. My last resort will be to just completely ditch using stringWithFormat all together, maybe it was only meant for simple UTF8Strings and basic symbols.
If you want to represent currency, is a lot better if you use a NSNumberFormatter with currency style (NSNumberFormatterCurrencyStyle). It reads the currentLocale and shows the currency based on it. You just need to ask its string representation and append to a string.
It will be a lot easier than managing unicode formats, check a tutorial here
This will give you the required result
NSString *str = #"Kč1.00";
str=[NSString stringWithFormat:#"%#%8#",[#" " stringByPaddingToLength:3 withString:#" " startingAtIndex:0],str];
Out Put : #" Kč1.00";
Just one more trick to achieve this -
If you like use it :)
[NSString stringWithFormat:#"%8s%#",[#"" cStringUsingEncoding:NSUTF8StringEncoding],str];
This will work too.

Read word by word a UITextView

i don't know whether this question has already been asked but i couldn't find anything about this.
I have a UITextView and i would like to be able to read single words from a text written by the users. This is an example:
i write on a textView this:
Obiwan is cool
then i have something like 3 string and store the single words that would result
string_1 = "Obiwan";
string_2 = "is";
string_3 = "cool";
What i'm looking for is like the Java's
s.useDelimiter(" ");
plus, to read the tableView,
while(s.hasNext()){
...
}
Thanks in advance.
You need to use NSString's equivalent of Java's split(), which is either
componentsSeparatedByCharactersInSet:
or
componentsSeparatedByString:
Both of these return an NSArray of word strings. If you pass a single space to the latter, it will do exactly what your Java example does. However, if you want to be more precise by including other whitespace and newlines, you use the former with an NSCharacterSet, like
NSArray *words = [self.textView.text componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

Objective-c RegEx variable names ($1, $2, etc.)

I have a Regular Expression in Objective-C and I need to know how to get a certain variable...
I want to find a string that has the letter "a" somewhere in it followed by any number (including zero) of B's, C's, and D's after it and at the first non-B,C,D I want to close my search statement. Then I want to replace the A with an F and add an F to the end of my search-string.
For example: "ZYXABCBBDBCBDEJKS" would search and return: "ZYXABCBBDBCBDEJKS" ... so the string I am now working with is "ABCBBDBCBDE", I want this string to turn into this string "FBCBBDBCBDEF" and then be put back into the original string... so the final returned string will be "ZYXFBCBBDBCBDEFJKS"
I'm new to RegEx but I gave it a shot with the below objective-c code and it didn't work... I think this is because my variables on the second line of code (at the "withTemplate" part) are wrong... I shouldn't use "$2" or "$1" should I?
code:
regex = [NSRegularExpression regularExpressionWithPattern:#"A(B|C|D)*([^B|C|D])"
options:0
error:nil];
modifiedString = [regex stringByReplacingMatchesInString:myString
options:0
range:NSMakeRange(0, [htmlstring length])
withTemplate:#"F$1$2F"];
In your regex - (B|C|D)* will only capture the last matched character out of (B|C|D), since * is out of the captured group. Also, in a character class, you don't need to use a pipe to alternate, as you did in 3rd part. So, either you use character class, or you use pipe to alternate in groups. And in this particular case, I would suggest to use character class in both place.
So, you can try changing your regex to:
"A([BCD]*)([^BCD])"

Resources