IOS NSDictionary element to NSString - ios

Hi I am trying to extract key value from NSDictionary, the dictionary value looks like below screen shot
I need to extract the value with key "TITLE" to NSString, using the code
NSDictionary* tmp = [self getDBRequest:req];
NSString * title =[tmp valueForKey:#"TITLE"];
But giving the the value like
Is there anything wrong with above code?
Edit:
NSLog(#"%#", tmp);
Gives the output
2015-12-31 11:04:52.530 SimpleTable[610:10059] (
{
DESCRIPTION = "30% OFF ON NEW ";
"IMAGE_URL" = "crowd.jpg";
TITLE = "GET 30% OFF";
}
)
Edit2
Actualy using the result of NSString * title =[tmp valueForKey:#"TITLE"]; I have to replace an element of NSMutableArray
And the code
NSMutableArray *array = [[NSMutableArray alloc]init];
[array addObject:#"Eezy"];
[array addObject:#"Tutorials"];
NSDictionary* tmp = [self getDBRequest:req];
NSString * title =[tmp valueForKey:#"TITLE"];
[array replaceObjectAtIndex:0 withObject:title];
Giving me the array modified some thing like below screen shot

Look at the first image in your question, the first line of the contents dump says "1 object".
Also look at the output of the NSLog, notice the parentheses (( & )) which surround the braces ({ & }), which in turn surround the key/value pairs.
Both these are telling you that tmp is not referencing an NSDictionary as you think, but an NSArray containing a single element and that element is an NSDictionary.
Now when you invoke valueForKey: on an array of dictionaries it does the key lookup on every dictionary in the collection and returns and array of results.
Which is why when you look at the second image in your question you see that its contents dump also starts with "1 object" - title is referencing an array containing one element, being your string.
This is also why, as mentioned in the comments, that using objectForKey: in place of valueForKey: causes an error - that method does not operate on arrays and so produces the unrecognized selector sent to instance error.
HTH

try like bellow code.
NSDictionary *tmp = #{#"DESCRIPTION" : #"30 OFF ON NEW",#"IMAGE_URL" : #"crowd.jpg",#"TITLE" : #"GET 30% OFF"};
//NSDictionary* tmp = [self getDBRequest:req];
NSArray *keyArray = [tmp allKeys];
NSString * title = [keyArray objectAtIndex:[keyArray indexOfObject:#"TITLE"]];//[keyArray objectAtIndex:0];
[array replaceObjectAtIndex:0 withObject:title];

Related

NSString in NSMutableArray isn't the same on myString

I have a problem with NSString and NSMutableArray.
When I retrieve a string from mutable array ,it has more white spaces, and I don't understand why it's happening.
I'll explain, I have an array and populate it by query (using sqlite3):
NSMutableArray *fileNameAttached = [[NSMutableArray alloc] initWithArray:[self.dbManager loadDataFromDB:query]];
and it's like this:
<__NSArrayM 0x15e233980>(
<__NSArrayM 0x15e26afd0>(
Allegato N. 1
)
)
When I retrieve the string Allegato N.1 with this code:
NSString *test = [NSString stringWithFormat:#"%#", [fileNameAttached objectAtIndex:0] ];
string test is like this:
(
"Allegato N. 1"
)
Why my string isn't only:
Allegato N.1
When I put it in a label it's not correct because contains () and white spaces.
The query for DB is:
NSString *query = [NSString stringWithFormat:#"SELECT fileName FROM Attach WHERE ID = '%#';",ticketID];
and works perfectly,in fact when I populate tableview cell it's OK. But I don't understand because my string test contains 3 line with more white spaces.
Please help Me.
Thank you and sorry for my english.
In your log there are two arrays.
(
(
Allegato N. 1
)
)
There are two round brackets thats means two array.
You are fetching data like NSString *test = [NSString stringWithFormat:#"%#", [fileNameAttached objectAtIndex:0] ];
That means first object of outer array so it is another array. so you need to do something like
NSArray *temp =[fileNameAttached objectAtIndex:0];
NSString *test = [NSString stringWithFormat:#"%#", [temp objectAtIndex:0] ];
I think you are using appcoda's DBManager class to do this. If it is so then you everytime got two array when load query.
Hope this will help :)

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.

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:#" "];

NSDictionary App Crash

Trying to read a plist and change my font color depending on the option that was selected in the following settings bundle.
The following is how I am trying to accomplish it:
NSString *path = #"/var/mobile/Library/Preferences/NCNotes.plist";
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
fontSize = [[dict objectForKey:#"slideSwitched"] floatValue];
if ([[dict objectForKey:#"noteColor"] valueForKey:#"Purple"]) {
noteView.textColor = [UIColor purpleColor];
} else {
noteView.textColor = [UIColor blackColor];
}
Any ideas why this is why my app is crashing? How do I read the values and change the color depending on what was selected?
It appears that the top level of your plist is an array, not a dictionary, because at the top it says "Item 1" where all of your content is within that. So you have a dictionary within an array. So you can change your code like this:
NSString *path = #"/var/mobile/Library/Preferences/NCNotes.plist";
NSArray *array = [[NSArray alloc] initWithContentsOfFile:path];
NSDictionary *dict = array[0];
You could also change the structure of your plist so that you have a dictionary as the root instead of an array.
Also, keys are supposed to be on the left-hand side and their values on the right-hand side, so I don't see a key "noteColor". You have a key "key" with a value "noteColor", so you'll need to make that correction. I'm also not seeing a "slideSwitched" key, though it might just be outside the bounds of your screenshot.
Also the following won't work:
[[dict objectForKey:#"noteColor"] valueForKey:#"Purple"]
Whatever you get from [dict objectForKey:#"noteColor"] isn't going to be a dictionary, so calling valueForKey: on that isn't going to give you what you want.
simply you should do this with document directory
NSString *contentPath=[[NSBundle mainBundle] pathForResource:#"PLIST_FILE_NAME" ofType:#"plist"];
NSDictionary *dictionary=[NSDictionary dictionaryWithContentsOfFile:contentPath];
write your logic after this, wait a minute , its seems like you dont have a key "noteColor" also. check your plist
Here is some example code documented up the wazoo. Hopefully it will help you understand how these plists and dictionaries work. Everything will be based on your plist file (which could definitely be improved upon, but that's up to you as I don't know your specific situation).
Your question is "How do I find color based on user selection?" I will assume you get the user selection as an int. Something like "User selected 7".
//Load your plist dictionary
NSString *path = #"/var/mobile/Library/Preferences/NCNotes.plist";
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
//Get the array of validValues and the array of validTitles
NSArray *valuesArray = [dict objectForKey:#"validValues"];
NSArray *titlesArray = [dict objectForKey:#"validTitles"];
//Now get the user selected index from the validValues array
int arraySelection = -1;
for(int i = 0; i < [valuesArray count]; i++)
{
NSNumber *number = [valuesArray objectAtIndex:i];
if([number intValue] == userSelectedInput)
{
arraySelection = i;
break;
}
}
if(arraySelection == -1)
{
//Not found in array
return;
}
//Now with that index get the title of the object that the user selected
NSString *userSelectedTitle = [titlesArray objectAtIndex:arraySelection];
//Now do your checking on what the user selected based on that:
if([userSelectedTitle isEqualToString:#"Purple"])
...
You could boil this down quite a bit. Currently your validValues array is completely useless. If it were out of order or missing numbers then it would be needed, but straight counting can be achieved by the validTitles array.

Searching dictionary works find with hard coded variable, but otherwise crashes

I have the following code to search the following dictionary:
//NSString *knownObject = #"3:40 am";
NSArray *temp = [itemDict allKeysForObject:knownObject];
NSString *key = [temp objectAtIndex:0];
NSLog(#"prayer: %#", key);
Dict:
{
asr = "4:23 pm";
dhuhr = "12:02 pm";
fajr = "1:16 am";
isha = "10:47 pm";
maghrib = "8:24 pm";
shurooq = "3:40 am";
}
When running the first line, it correctly returns "shurooq". However, when I use my variable:
NSArray *temp = [itemDict allKeysForObject:nextPrayerTime];
The log output of nextPrayerTime is simply 3:40 am as expected.
Why is this not working?
Many thanks!
Checkout the value of nextPrayerTime, if itemDict contain any object same as nextPrayerTime then [itemDict allKeysForObject:nextPrayerTime]; will return an array of keys otherwise it will return empty array.
In your current case anyhow you get an empty array but when you try to access [temp objectAtIndex:0] then compiler couldn't find any object and it gets an array out of bound exception and this cause the crash of your app....
To overcome this exception you should check the count of objects in array...
NSArray *temp = [itemDict allKeysForObject: nextPrayerTime];
if([temp count] > 0) {
NSString *key = [temp objectAtIndex:0];
NSLog(#"prayer: %#", key);
} else
NSLog(#"NO Object Found");
What is the value of nextPrayerTime?
According to the docs, allKeysForObject: returns
A new array containing the keys corresponding to all occurrences of anObject in the dictionary. If no object matching anObject is found, returns an empty array.
Based on the information given I would guess you are getting back an empty array and when you call [temp objectAtIndex:0] you are accessing an index that does not exist and getting an out of bounds exception.
I am not a 100% sure of my answer, but is the method isEqualToString used for comparison of the objects when the object is a NSString?
Otherwise you probably need to compare to the original object in the dictionary (using the same NSString).

Resources