How can i retrieve "extract" field from wikipedia api? - ios

This is the link which I have to parse it in Objective C:
http://en.wikipedia.org/w/api.php?action=query&prop=extracts&format=json&exsentences=2&exintro=&titles=USA
If you clearly look at the link the word "USA" is actually going to change as per user requests.In the JSON information after pages key you can actually see a number before pageid. How can I access it? If that field is static I can access with that particular key. But it seems like that number is dynamic according to the user search. My aim is to access "extract" key. If I want to do that I have to go inside to that number which is a dynamic one. I appreciate any kind of help. Thanks in advance.

Under "pages" you are getting a dictionary with keys that are the same as the ids (just strings). It seems your question circles around the fact that you do not know these keys beforehand.
Once you extracted the pages dictionary, you can iterate through the keys like this:
for (NSString *idString in pages.allKeys) {
NSDictionary *content = pages[idString];
NSString *extract = content["extract"];
// do something with extract
}
If you just want the any key or you are sure there is only one, you can instead create the content dictionary with
NSDictionary *content = pages[pages.allKeys.firstObject];

One expression doing the same as Mundi's answer:
NSString *extract =
[[[array valueForKeyPath:#"query.pages"] allObjects].firstObject
valueForKey:#"extract"];

Related

objective-c JSON literals, nested - most elegant solution?

Say you do this,
NSString *teste = yourData[#"title"];
no problem if "title" is completely missing in the json: you just get null. If you do this:
NSString *teste = yourData[#"location"][#"city"];
if "city" is missing in the json nest, no problem. if the whole "location" section does not exist, again no problem
However! You'll often see json like this, " largeImage = "<null>"; "
In that case, the app will crash if you are using the code above.
In practice you have to do this:
NSString *imageUrl = nil;
if ([yourResults[thisRow][#"largeImage"] isKindOfClass:[NSDictionary class]])
imageUrl = yourResults[thisRow][#"largeImage"][#"URL"];
My question was really:
is there some dead clever way to perhaps override the literal syntax (ie, override the underlying message, perhaps??) to cover this problem?
So essentially, make this concept [#"blah"] basically first check that indeed it is a dictionary at hand, before trying the operation.
It's a shame because, effectively, you can never use this wonderful syntax
yourData[#"location"][#"city"]
in practice, due to the problem I outline.
PS sorry for the earlier confusion on this question, fixed by Paramag. below - good one Paramag.
Personally i use with JSON category which returns null instead NSNull so my code looks:
[[json objectForKeyNotNull:#"Key"] objectForKeyNotNull:#"Other"]
As you want to have code shorter, i think i would create the category on NSDictionary which could be used as :
[json objectForPath:#"Key.Value"]
Which would expand the path into the keys.
There is some nice gist which looks like it's doing it:
https://gist.github.com/Yulong/229a62c1188c3c024247#file-nsdictionary-beeextension-m-L68
to check this kind of null , you can use valueForKeyPath:
NSString *teste = [CLOUD.yourData[thisRow] valueForKeyPath:#"location.city"];
it will first check for "location" and then for "city".
I would say this is a problem with your schema. null in JSON and a dictionary (called an "object") in JSON are different types of things. The fact that your key can have a value that is sometimes null and sometimes a dictionary seems to me that you guys are not following a rigorous schema.
A good design would have the key either not be there, or if it is there, its value is guaranteed to be a dictionary. In such a case, the Objective-C code NSString *teste = yourData[#"location"][#"city"]; would work without modification because if the key "location" didn't exist, then its value would be nil in Objective-C, and subsequent accesses won't crash, and will also return nil.

Objective C converting NSDictionary valueForKeyPath into a string

I have a NSDictionary that I am trying to get some strings out of. The name of the dictionary is called tweets. I can get the user name and tweet by doing the following.
NSDictionary *tweet = self.detailItem;
NSString *username = [[tweet objectForKey:#"user"] objectForKey:#"name"];
NSString *tweetText = [tweet objectForKey:#"text"];
If I NSLog the results I get; username is "person's username" and tweetText is "person's tweet." These are both NSString that I can manipulate.
However, I also need to get the actual URL from the tweet, not the shortened one. So I have found it in the dictionary with valueForKeyPath. I need this as a string and have tried the following.
NSString *url = [tweet valueForKeyPath:#"entities.urls.display_url"];
I can NSLog this as well and I get the proper information. But I think it comes out as an Array? The NSLog looks like this.. url is ( "url goes here" ). With the brackets and quotes. This is not a string like the others. I am assuming it is because of the valueForKeyPath. When I tried to use url hasPrefix, it doesn't like that and mentions you can't have hasPrefix with and array. But I also tried to use multiple objectForKey with entities, urls, and display_url. But this does not work. Is there any way to get my entry into a string format. I have looked over some SO questions and on the web, but can't find anything that is useful for me. Any help will by much appreciated. Thanks for your time
The keyPath entities.urls.display_url traverse an array of arrays and flattens that to return an array of display_urls. If you were confident that there would be only one url within that hierarchy you could use
NSString *url = [[tweet valueForKeyPath:#"entities.urls.display_url"] lastObject];
If there are multiple entities with URLs you may have to traverse the entities and urls to determine the URL in which you are interested. Or you may be able to use firstObject if what you are really looking for is entities.urls.[0].display_url
Per Twitter's documentation on entities, entities is a dictionary and urls is an array of dictionaries.
When you perform ... valueForKeyPath:#"entities.urls.display_url"] you do the same thing as ... valueForKey:#"entities"] valueForKey:#"urls] valueForKey:#"display_url"].
Per NSDictionary's documentation, its valueForKey: returns the same thing as objectForKey: if — as in this case — the key in question doesn't start with an #.
So the entities part of valueForKeyPath: returns an array of objects.
Per NSArray's documentation, its valueForKey: returns an array comprised of the result of calling valueForKey: on each object in the array individually.
Given that each thing in the entities array is a dictionary, what you therefore get back is an array of the display_url key for every entity in the tweet.
So I think your problem is that you expect to get "the actual URL from the tweet" (emphasis added). Tweets may contain arbitrary many links outward, not merely one — entities represent ranges of characters with special meanings like links, hashtags and similar. So you end up with an array rather than a single value.

NSDictionary Vs. NSArray

I am reading on objective-c (a nerd ranch book), and I can't help thinking about this question: How do I decide which collection type, NSArray or NSDictionary (both with or w/o their mutable subclasses), to use when reading content from URL?
Let's say am reading JSON data from a PHP script (a scenario am dealing with), which to use? I know it is stated in many references that it depends on structure of data (i.e. JSON), but could a clear outline of the two structures be outlined?
Thank you all for helping :)
NSArray is basically just an ordered collection of objects, which can be accessed by index.
NSDictionary provides access to its objects by key(typically NSStrings, but could be any object type like hash table).
To generate an object graph from a JSON string loaded via a URL, you use NSJSONSerialization, which generates an Objective-C object structure. The resulting object depends on the JSON string. If the top-level element in your JSON is an array (starts with "["), you'll get an NSArray. If the top-level element is a JSON object (starts with "{"), you'll get an NSDictionary.
You want to use NSArray when ever you have a collection of the same type of objects, and NSDictionary when you have attributes on an object.
If you have, lets say a person object containing a name, a phone number and an email you would put it in a dictionary.
Doing so allows the order of the values to be random, and gives you a more reliable code.
If you want to have more then one person you can then put the person objects in an array.
Doing so allow you to iterate the user objects.
"withContentOfURL" or "withContentOfFile" requires the data in the URL or the file to be in a specific format as it is required by Cocoa. JSON is not that format. You can only use these methods if you wrote the data to the file or the URL yourself in the first place, with the same data. If you write an NSArray, you can read an NSArray. If you write an NSDictionary, you can read an NSDictionary. Everything else will fail.

NSDictionary with NSObjects as keys

I'm trying to create an NSDictionary that keeps track of calling objects for a function. I'd like to create a unique string for each object without knowing anything about it. My first thought is to use the memory address of the object's pointer, but I'm not sure how to do that.
Any thoughts? I need to use some sort of unique id from an NSObject as the keys in my dictionary.
If your application supports iOS6 only check the NSDictionaryOfVariableBindings macro.
The code would be something like :
// Create the dictionary
NSObject *firstObject = [NSString stringWithString:#"My first item"];
NSObject *secondObject = #"[#"an", #"array", #"of", #"strings"]";
NSDictionary *theDic = NSDictionaryOfVariableBindings(firstObject, secondObject);
// Access data
NSString *singleString = [theDic objectForKey:#"firstObject"];
NSArray *listOfStrings = [theDic objectForKey:#"secondObject"];
My suggestion is not to use a dictionary. If you were to place them into an array, you could think of it as a dictionary with automatically generated unique keys (the indexes). It's really exactly what you are describing. If for some reason you have to use a dictionary, my suggestion is to implement that same model I'm speaking of, but you would have to generate and maintain the keys.
While I agree that your solution sounds like it may not be the best approach, have you considered -hash in the NSObject protocol? All NSObjects should return one. Be forewarned that it's a hash, so there's a chance that two different objects could have the same hash.
You could also consider a category on NSObject that your collection implements. The category could generate a UUID to use as a key.

how to get data form NSMutablearray in to NSString

Hello.......
in my apps, i have problem with xml parising .i have same tags differentiate with integer value.each tag has different value.
now the problem me facing is accessing this value for that particular tag only.
plz anybody have idea abat this.
let me know.
mean's the problem is that i have one MutableArray and all record in it. and i want to show some values in one view and reaming some value show in another view and reaming in another view..
But the MutableArray is same..
and one more thing is that i want to get tag value
<subject>XYZ</subject>
the output is subject i want.
i do not need of XYZ i need only subject..
sorry i can not show what i want but please understand my question and give me the answer
Thanks
Use NSMutableDictionary instead NSMutableArray.
From documentation.
The NSMutableDictionary class declares the programmatic interface to
objects that manage mutable associations of keys and values. It adds
modification operations to the basic operations it inherits from
NSDictionary.

Resources