Accented character incorrectly encoding in NSString Array - ios

?I'm building a NSMutableArray of NSStrings from a list and some of the letters are accented (Turkish). I have been able to encode into a NSString and NSLog the results. But when I add that NSString to my NSMutableArray the encoding is incorrect.
This works:
NSString* temp = [[NSString alloc] init];
char *str = "üç";
temp = [NSString stringWithUTF8String:"üç"];
NSLog(#"str: %#",temp);
Logged output:
2012-06-09 09:09:18.398 Fluent[1821:f803] str: üç
When I try to add it to my NSMutableArray like this:
ones = [NSArray arrayWithObjects:#"",#"bir",#"iki",temp,#"dört",#"beş",#"altı",#"yedi",#"sekiz",#"dokuz",nil];
NSLog(#"ones: %#",ones);
It loses the encoding:
2012-06-09 09:09:18.399 Fluent[1821:f803] ones: (
"",
bir,
iki,
"\U00fc\U00e7",
"d\U00f6rt",
"be\U015f",
"alt\U0131",
yedi,
sekiz,
dokuz)
Any ideas on how to do this? The posts I have read around this area seem to be focused on transfer over HTTP.
I'd like a simpler approach such as to encode a C-string if this is necessary and then unstring by spaces into the array.

Your strings aren't incorrectly encoded. What you see is an artifact of writing a complete array to the log. In this case, the array is first converted to the property list format and then written to the log.
If you create a loop and write each element separately to the log, you'll see that everything is ok:
NSUInteger count = [ones count];
for (NSUInteger i = 0; i < count; i++) {
NSLog(#"element %d: %#", i, [ones objectAtIndex: i]);
}

This is not losing the encoding, try to add the strings from the nsarray to a UILabel or UITextField and it should be correct
This behavior of writing the Unicode representation happens only in the console when you NSLog

Related

How can I change substring(s) in an array of strings in Objective-C?

I have a weird error with decoding & sign so its always shown as &, so && will be &&, a&b is shown as a&b etc.
I have those weird characters in my array of strings sometimes, so I want to remove them. To be more clear, if I have an array like this:
"str1", "a&b", "12345", "d&&emo&"
I want to it to be:
"str1", "a&b", "12345", "d&&emo&"
So all & should be changed into just &.
This is the code I tried, but it didn't help. Elements are not changing their values:
for (int i = 0; i <= self.array-1; i++)
{
NSLog(#"%#", self.array[i]);
[self.array[i] stringByReplacingOccurrencesOfString:#"&" withString:#"&"];
NSLog(#"%#", self.array[i]);
}
I am new to Objective-C.
NSString instances are immutable, which means you can't change them once they are created. The stringByReplacingOccurencesOfString:withString: method actually returns a new NSString instance. You could use NSMutableString, or alternatively, you can create a new array containing the replacement strings, e.g.:
NSMutableArray *newArray = [NSMutableArray array];
for (NSString *input in self.array)
{
NSString *replacement = [input stringByReplacingOccurrencesOfString:#"&" withString:#"&"];
[newArray addObject:replacement];
}
self.array = newArray;

Display Unicode String as Emoji

I currently receive emojis in a payload in the following format:
\\U0001F6A3\\U0000200D\\U00002640\\U0000FE0F
which represents "🚣‍♀️"
However, if I try to display this, it only shows the string above (escaped with 1 less ), not the emoji e.g.
NSString *emoji = payload[#"emoji"];
NSLog(#"%#", emoji) then displays as \U0001F6A3\U0000200D\U00002640\U0000FE0F
It's as if the unicode escape it not being recognised. How can I get the string above to show as an emoji?
Please assume that the format the data is received in from the server cannot be changed.
UPDATE
I found another way to do it, but I think the answer by Albert posted below is better. I am only posting this for completeness and reference:
NSArray *emojiArray = [unicodeString componentsSeparatedByString:#"\\U"];
NSString *transformedString = #"";
for (NSInteger i = 0; i < [emojiArray count]; i++) {
NSString *code = emojiArray[i];
if ([code length] == 0) continue;
NSScanner *hexScan = [NSScanner scannerWithString:code];
unsigned int hexNum;
[hexScan scanHexInt:&hexNum];
UTF32Char inputChar = hexNum;
NSString *res = [[NSString alloc] initWithBytes:&inputChar length:4 encoding:NSUTF32LittleEndianStringEncoding];
transformedString = [transformedString stringByAppendingString:res];
}
Remove the excess backslash then convert with a reverse string transform stringByApplyingTransform. The transform must use key "Any-Hex" for emojis.
NSString *payloadString = #"\\U0001F6A3\\U0000200D\\U00002640\\U0000FE0F";
NSString *unescapedPayloadString = [payloadString stringByReplacingOccurrencesOfString:#"\\\\" withString:#"\\"];
NSString *transformedString = [unescapedPayloadString stringByApplyingTransform:#"Any-Hex" reverse:YES];
NSLog(#"%#", transformedString);//logs "🚣‍♀️"
I investigated this, and it seems you may not be receiving what you say you are receiving. If you see \U0001F6A3\U0000200D\U00002640\U0000FE0F in your NSLog, chances are you are actually receiving \\U0001F6A3\\U0000200D\\U00002640\\U0000FE0F at your end instead. I tried using a variable
NSString *toDecode = #"\U0001F6A3\U0000200D\U00002640\U0000FE0F";
self.tv.text = toDecode;
And in textview it is displaying the emoji fine.
So you got to fix that first and then it will display well.

How to pass Array to SOAP API?

I need to pass this array to SOAP API as a parameter. The back-end guy is new to building APIs (C#/.NET) and I have never implemented this kind of API before. There are 4-5 SO question related to this. But none of them were the solution as per my query.
NSArray *arr = [NSArray arrayWithObjects:#"1",#"2", nil];
NSString *soapURL = #"http://tempuri.org/IService1/addRecord";
NSString *soapBody = [NSString stringWithFormat:#"<addRecord xmlns=\"http://tempuri.org/\">"
"<id>%#</id>"
"<title>%#</title>"
"<record>%#</record>"
"</addRecord> \n” ,#“1”,#“abc", arr ];
NSLog(#"%#",soapBody);
Error:
value in string The formatter threw an exception while trying to deserialize the message: Error in deserializing body of request message for operation 'addRecord'. End element 'record' from namespace 'http://tempuri.org/' expected. Found text '(
1,
2
)'.
One thing I came to know that I cannot pass array directly in to soapBody. What what is the alternative?
The API is working fine at the back-end.
some comments:
NSArray *arr = [NSArray arrayWithObjects:#"1",#"2", nil];
please write instead the modern form:
NSArray *arr = #[#"1",#"2"];
Also, your question is filled with wrong types of quotes (“1”). Make sure to use the regular quotes, i.e. ".
When you use "stringWithFormat" with %# and provide an array, you must understand what you are getting there. let's try:
NSArray *arr = #[#"1",#"2"];
NSString *str = [NSString stringWithFormat:#"<%#>", arr];
NSLog(#"%#", str);
The result is:
<(
1,
2
)>
It means that between your <record> and </record> you inserted two numbers separated by a comma and surrounded by parentheses, plus some \n.
Is this what your server is expecting?
So I am not solving your problem, but you must format your string the right way and verify it using your NSLog command. Hoping it is helping.
EDIT
If for example you need to provide the values of the array within <value>...</value> than you can do this:
NSArray *arr = #[#"1", #"2"];
NSMutableString *mStr = [NSMutableString string];
for (NSString *value in arr) {
[mStr appendFormat:#"<value>%#</value>", value];
}
NSLog(#"<record>%#</record>", mStr);
And the result will be
<record><value>1</value><value>2</value></record>
Finally I resolved this issue with this code:
NSString *soapBody = [NSString stringWithFormat:#"< addRecord xmlns=\"http://tempuri.org/\" xmlns:arr=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\" > \n"
"<ID>1</ID>\n"
"<title>ABC</title>\n"
"<record>\n"];
for (int i=0; i<arrRecord.count; i++) {
soapBody = [NSString stringWithFormat:#"%# <arr:int>%#</arr:int>\n",soapBody,arrRecord[i]];
}
soapBody = [NSString stringWithFormat:#"%# </record></addRecord> \n",soapBody];
I needed to define "arr" in the parent node and type of element(int) in the record array.

Unknown quotation marks added to string object in NSMutableArray after for loop

I have an array of NSString objects, the objects have some unneccessary chars (one object looks like this in the console: "\"stringContent\"") that I'm removing with the below code. It works correctly, however when I log arr1 50-60% of the strings got a quotation marks like this "stringContent", the others don't have it. Actually my problem is that I don't have an why it happens, because when I log the strings in the for loop they don't have the quotation marks. Do anybody has an idea what can causes this?
NSMutableArray * arr1 = [[NSMutableArray alloc ]init];
for (NSString *str in self.stringArray) {
NSString *newString = [str substringToIndex:[brand length]-1];
NSString *nwstr = [newString substringFromIndex:1];
[arr1 addObject:nwstr];
NSLog(#"string %#", nwstr);
}
NSLog(#"array %#", arr1);
Other thing that might be helpful, when I call this every object appears in the console, it's like the quotation marks are hidden for the containsString method, because a lot of them don't meet the requirement of the if statement.
for (NSString *str in arr1) {
if (![str containsString:#"\""]) {
NSLog(#"XXX %#", str);
}
}
When you NSLog an NSArray or NSDictionary, the elements are displayed in a log format which MAY (or may not) include gratuitous quotation marks, escaped characters, etc. Specifically, quotation marks are used around strings, EXCEPT when the strings contain no non-alphabetic characters or blanks.
More detail: What actually happens is that NSLog internally invokes [NSString stringWithFormat:] or one of its kin to format the text to be logged. stringWithFormat:, in turn, invokes the description method of each object in the parameter list that corresponds to a %# format directive. It is the description method of NSArray and NSDictionary which adds the extra characters.

Passing a _CFNSString into an NSString

I have a loop that identifies elements of a webpage via its HTML and extracts the sections I need. I'm wanting to build an array or (very) long string of the extracted text which can be used later.
The extraction uses TFHpple from GitHub. The problem seems to lie with the extracted text being a _CFNSString, and these don't allow me to transpose them into a NSString or NSMutuableArray.
The code I'm using is:
NSArray *webNodes = [webParser searchWithXPathQuery:tutorialsXpathQueryString];
NSString *extractedText = [[NSString alloc] init];
NSMutableArray *extractedArray = [[NSMutableArray alloc] initWithCapacity:0];
for (TFHppleElement *element in webNodes) {
Extraction *extraction = [[Extraction alloc] init];
[extractedArray addObject:extraction];
extraction.title = [[element firstChild] content];
extractedText = extraction.title;
NSLog(#"\n\nTitle: %#", extractedText);
}
The NSLog at this point shows me extractedText holds I'm after for each loop, breaking the code shows extractedText to be a _CFNSString.
If I try adding
text = [text StringByAppendingString extractedText];
(with 'text' being an NSString initialised before the loop) as the last step of the loop I get a null value. Its the same if I try adding text or extraction.title directly into an array.
I found this question Convert NSCFString to NSString but the conversion seems to be going the other way (NSString to CFNSString). When I added equivalent code I got bridging errors and the code doesn't run.
How can I collect the data within extraction.title to build a string or array that can be used later?
You said you only want a text.
Get it in one line of code for array:
NSArray *extractedArray = [webNodes valueForKeyPath:#"firstChild.content"];
For string:
NSString *extractedText = [webNodes valueForKeyPath:#"firstChild.content"] componentsJoinedByString:#" "];

Resources