json populate table view controller wont work - ios

I've been following a tutorial on youtube on how to load external data from a database on to a iOS application. I understand the concept and how it works etc. But I'm having an error even though I'm following the video and from looking online it seems to be a common error.
- (void) retrieveData
{
NSURL * url = [NSURL URLWithString: getDataURL];
NSData * data = [NSData dataWithContentsOfURL:url];
jsonArray = [NSJSONSerialization JSONObjectWithData: data options:kNilOptions error:nil];
//set up our cities array
citiesArray = [[NSMutableArray alloc] init];
// loop through our json array
for (int i =0; i< jsonArray.count; i++)
{
//create our city object
NSString * cID = [[jsonArray objectAtIndex:i] objectForKey:#"id"];
NSString * cName = [[jsonArray objectAtIndex:i] objectForKey:#"cityName"];
NSString * cState = [[jsonArray objectAtIndex:i] objectForKey:#"cityState"];
NSString * cPopulation = [[jsonArray objectAtIndex:i] objectForKey:#"cityPopulation"];
NSString * cCountry = [[jsonArray objectAtIndex:i] objectForKey:#"country"];
// Add the city object to our cities array
[citiesArray addObject:[[City alloc]initWithCityName:cName andCityState:cState andCityCountry:cCountry andCityPopulation:cPopulation andCityID:cID]];
}
//reload our table view
[self.tableView reloadData];
}
The code fails on the third line.
jsonArray = [NSJSONSerialization JSONObjectWithData: data options:kNilOptions error:nil];
Why is that? Any suggestions? The jsonArray has already been created, so I can't understand why it won't work.

I checked your code & i don't think there is any error.
I hope you've declared NSMutableArray *jsonArray in header (.h) file.
If you getting error in thos line :
jsonArray = [NSJSONSerialization JSONObjectWithData: data options:kNilOptions error:nil];
than replace kNilOptions with simply nil.
If you getting crash than it might be because nil data. In that case you have to put condition before you store data in array something like this :
if (data != nil)
{
jsonArray = [NSJSONSerialization JSONObjectWithData: data options:nil error:nil];}
Hope it'll help.

Related

How to parse a JSON dictionary and put the keys and values in separate arrays - Objective C

I'm trying to parse www.fixer.io JSON to get currency data. I've been having trouble parsing the JSON and trying to separate the keys and values from the "rates" dictionary. I need them separate so I can put them in arrays to display the currency name (ex: USD, EUR, JPN) and their respective rates.
I've read that I have to use the "allKeys" and "allValues" to do this but so far I'm having no luck. Any ideas?
NSURL *fixerURL = [NSURL URLWithString:#"http://api.fixer.io/latest?base=USD"];
NSData *data = [NSData dataWithContentsOfURL:fixerURL];
NSError *error;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSMutableArray *arr = [[NSMutableArray alloc]init];
NSMutableArray *arr2 = [[NSMutableArray alloc]init];
NSArray *names;
NSArray *rates;
for (names in json) {
names = [json allKeys];
for (rates in json) {
rates = [json allValues];
}
[arr addObject:names];
[arr2 addObject:rates];
}
self.currencyList = arr;
self.currencyRates = arr2;
[self updateTableView];
Here is the JSON ---> http://api.fixer.io/latest?base=USD
Hope this will help you,
NSURL *fixerURL = [NSURL URLWithString:#"http://api.fixer.io/latest?base=USD"];
NSData *data1 = [NSData dataWithContentsOfURL:fixerURL];
NSError *error;
NSDictionary *json1 = [NSJSONSerialization JSONObjectWithData:data1 options:kNilOptions error:&error];
NSLog(#"%#",json1);
NSDictionary *json = [[NSDictionary alloc]initWithDictionary:[json1 objectForKey:#"rates"]];
NSMutableArray *arr = [[NSMutableArray alloc] initWithArray:[json allKeys]];
NSMutableArray *arr2 = [[NSMutableArray alloc]initWithArray:[json allValues]];
NSLog(#"%#",arr);
NSLog(#"%#",arr2);
as the rates key contains a dictionary not an array so we can’t get country name and currency as dictionary format
if you want to get the country name and currency in different array so you need to get them separately like bellow
NSArray *arrKeys = [[json valueForKey:#"rates"] allKeys];
NSArray *arrValues = [[json valueForKey:#"rates"] allValues];
Based on your JSON response you have to get yoiur all currency rate as below
NSMutableArray *allCurrencyKey = [[json valuesForKey:#"rates"] allKeys];
NSMutableArray *allRates = [json valueForKey:#"rates"];
for(NSString *strCurKey in allCurrencyKey)
{
NSLog (#" %# rate is %# ", strCurKey, [allRates valueForKey :strCurKey ]);
}
Hope this will helps you.
I'm not sure what error you're getting, but when I try to run this code I get data coming back as nil. Which of course crashes the app.
It probably has something to do with the method you are using to fetch the JSON.
dataWithContentsOfURL: should not be used for network-based URLs.
dataWithContentsOfURL:
To fetch data over the network, take a look at NSURLSession.
Use below code to get Rates Nad Currency Names
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
By this response you can get all rates:
NSMutableDictionary *rates = [json objectForKey:#"rates"];
//Get All Currency Names by `allKeys`.
NSArray *currencyTitles = [rates allKeys];
for(NSString *currencyName in currencyTitles){
//Get Value.
NSString *aStrCurValue = [rates objectForKey:currencyName];
}

JSON String with Arrays iOS

My APP gets a JSON string from a api call JSON string has objects and a array in it. This is what i have done so far but i couldn't get the values from it . advice me please and I'm new to iOS .This is my JSON String :
{
"Id":"0d95a9f6-c763-4a31-ac6c-e22be9832c83",
"Name":"john",
"ProjectName":"project1",
"StartDate":"\/Date(1447200000000)\/",
"Documents":
[{
"Id":"2222a","Name":"book1","ContentType":"application/pdf"
},
{
"Id":"3718e","Name":"Toolbox","ContentType":"application/fillform"
}]
}
Code
NSString *URLString = [NSString stringWithFormat:#"http://mysite/API/Assignments?"];
NSURL *url = [NSURL URLWithString:URLString];
NSData *data=[NSData dataWithContentsOfURL:url];
json=[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
assignArray=[[NSMutableArray alloc]init];
for (int i=0; i<json.count; i++) {
NSString *aID=[[json objectAtIndex:i]objectForKey:#"Id"];
NSString *uName=[[json objectAtIndex:i]objectForKey:#"Name"];
NSString *pName=[[json objectAtIndex:i]objectForKey:#"ProjectName"];
//[self initwithUserID:uID userName:uName proName:pName];
// [self retrieveAssignmentDetails:aID];
AssignmentsJson *assignment=[[AssignmentsJson alloc]initwithassignID:aID userName:uName proName:pName];
[assignArray addObject:assignment];
your json is not array so parse like following
NSString *aID = json[#"Id"];
NSString *uName = json[#"Name"];
NSString *pName = json[#"ProjectName"];
NSString *startDate = json[#"StartDate"];
NSArray *documents = json[#"Documents"];
for (NSDictionary *item in documents) {
NSString *itemID = item[#"Id"];
NSString *itemName = item[#"Name"];
NSString *itemContentType = item[#"ContentType"];
}
Your Json Object is NSDictionary. so you can directly get data using valueForKey
NSDictionary *json=[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
NSString *aID = json[#"Id"];
NSString *uName = json[#"Name"];
NSString *pName = json[#"ProjectName"];
for Id,Name and ContentType is inside your array object within your NSDictionary object.
so you can get those values accessing array index.
NSArray *arr = json[#"Documents"];
for (int i=0; i<arr.count; i++) {
NSString *aID=[[arr objectAtIndex:i]objectForKey:#"Id"];
NSString *uName=[[arr objectAtIndex:i]objectForKey:#"Name"];
NSString *cType=[[arr objectAtIndex:i]objectForKey:#"ContentType"];
}
You should learn NSArray and NSDictionary Structure first. it will help you in future. Hope this will help you.
you can do it by following way.
Your Json is in NSDictionary format.
NSData * data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:#"http://mysite/API/Assignments?"]];
NSDictionary * dicResponse = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
if(dicResponse){
NSString * strID = [dicResponse valueForKey:#"Id"];
NSString * strName = [dicResponse valueForKey:#"Name"];
NSString * strProjectName = [dicResponse valueForKey:#"ProjectName"];
NSString * strDate = [dicResponse valueForKey:#"StartDate"];
NSArray * arrDocuments = [NSArray arrayWithArray:[dicResponse valueForKey:#"Documents"]];
for (int i=0; i< arrDocuments.count; i++) {
NSString * ID=[[arrDocuments objectAtIndex:i]valueForKey:#"Id"];
NSString * Name=[[arrDocuments objectAtIndex:i]valueForKey:#"Name"];
NSString * Type=[[arrDocuments objectAtIndex:i]valueForKey:#"ContentType"];
}
}

Using NSArray and NSDictionary to access a JSON object without a root element

Here's an example of my data:
[
{
code: "DRK",
exchange: "BTC",
last_price: "0.01790000",
yesterday_price: "0.01625007",
top_bid: "0.01790000",
top_ask: "0.01833999"
}
]
I'm trying to retrieve the value for last_price by loading the contents of my NSDictionary into an Array.
NSURL *darkURL = [NSURL URLWithString:#"https://api.mintpal.com/v1/market/stats/DRK/BTC"];
NSData *darkData = [NSData dataWithContentsOfURL:darkURL];
NSError *error = nil;
NSDictionary *darkDict = [NSJSONSerialization JSONObjectWithData:darkData options:0 error:&error];
self.darkPosts = [NSMutableArray array];
NSArray *darkPostArray = [darkDict objectForKey:#""];
for (NSDictionary *darkDict in darkPostArray) {...
But my json doesn't have a root element, so what do I do?
Additionally, when using the suggested answer, the output is ("...
- (void)viewDidLoad{
[super viewDidLoad];
NSURL *darkURL = [NSURL URLWithString:#"https://api.mintpal.com/v1/market/stats/DRK/BTC"];
NSData *darkData = [NSData dataWithContentsOfURL:darkURL];
NSError *error = nil;
NSDictionary *darkDict = [NSJSONSerialization JSONObjectWithData:darkData options:0 error:&error];
NSString *lastP = [darkDict valueForKey:#"last_price"];
self.dark_label.text = [NSString stringWithFormat: #"%#", lastP];
}
It looks like you are wanting to iterate over your results. The root element is an array not a dictionary so you can just start iterating
NSError *error = nil;
NSArray *items = [NSJSONSerialization JSONObjectWithData:darkData
options:kNilOptions
error:&error];
if (!items) {
NSLog(#"JSONSerialization error %#", error.localizedDescription);
}
for (NSDictionary *item in items) {
NSLog(#"last_price => %#", item[#"last_price"]);
}
If you literally just want to collect an array of the last_price's then you can so this
NSArray *lastPrices = [items valueForKey:#"last_price"];
Convert the JSON to an NSArray with NSJSONSerialization. Then access the value:
NSData *darkData = [#"[{\"code\":\"DRK\",\"exchange\": \"BTC\",\"last_price\": \"0.01790000\",\"yesterday_price\": \"0.01625007\",\"top_bid\": \"0.01790000\"}, {\"top_ask\": \"0.01833999\"}]" dataUsingEncoding:NSUTF8StringEncoding];
NSArray *array = [NSJSONSerialization JSONObjectWithData:darkData
options:0
error:&error];
NSString *value = array[0][#"last_price"];
NSLog(#"value: %#", value);
NSLog output:
value: 0.01790000
If you are having trouble post the code you have written to get some help.
-- updated for new OP code:
The web service returns a JSON array or dictionaries not a JSON dictionary. First you have to index into the array and then index into the dictionary.
NSURL *darkURL = [NSURL URLWithString:#"https://api.mintpal.com/v1/market/stats/DRK/BTC"];
NSData *darkData = [NSData dataWithContentsOfURL:darkURL];
NSError *error = nil;
NSArray *darkArray = [NSJSONSerialization JSONObjectWithData:darkData options:0 error:&error];
NSDictionary *darkDict = darkArray[0];
NSString *lastP = [darkDict valueForKey:#"last_price"];
NSLog(#"lastP: %#", lastP);
NSLog output:
lastP: 0.01970000
Note that the two lines:
NSDictionary *darkDict = darkArray[0];
NSString *lastP = [darkDict valueForKey:#"last_price"];
can be replaced with the single line using array indexing:
NSString *lastP = darkArray[0][#"last_price"];
Where the "[0]" gets the first array element which is a NSDictionary and the "[#"last_price"]" gets the names item from the dictionary.

Passing Array to UIWebView

I currently am pulling directions from google and storing them into an array. I then have an integer for the amount of directions found, and have the forloop displaying them via NSLog properly (with the html included)
My question is, how do I make this into a UIWebView so that it properly displays this information in a list?
Here is my code so far:
NSError *error;
NSString *currentLoc = #"Hyannis, MA";
NSString *directionsString = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/directions/json?origin=%#&destination=%#, %#, %#&sensor=false", currentLoc, [self.selectedEvent objectForKey:#"eventAddress"], [self.selectedEvent objectForKey:#"eventCity"], [self.selectedEvent objectForKey:#"eventState"]];
directionsString = [directionsString stringByReplacingOccurrencesOfString:#" " withString:#"+"];
NSData *jsonResponse = [NSData dataWithContentsOfURL:[NSURL URLWithString:directionsString]];
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:jsonResponse options:kNilOptions error:&error];
self.directionsArray = [[[[jsonDict valueForKey:#"routes"] valueForKey:#"legs"] valueForKey:#"steps"] valueForKey:#"html_instructions"];
NSUInteger total = [self.directionsArray count];
for (int i = 0; i < total; i++)
{
NSString *statusString = [jsonDict valueForKey:#"status"];
NSLog(#"JSON Response Status:%#", statusString);
NSLog(#"Direction: %#", [self.directionsArray objectAtIndex:i]);
}

Protect against index out of bounds

I am having trouble only executing objectAtIndex if I have values present.
My code:
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
NSDictionary *results = [json objectForKey:#"d"];
NSString *error = [results objectForKey:#"error"];
NSLog(#"results::%#", [results objectForKey:#"agency"]);
if ( results !=nil)
{
item = [[results objectForKey:#"agency"] objectAtIndex:0];
codeItem = [[results objectForKey:#"agency"] objectAtIndex:1];
}
It works fine if I have data in the json but if the json comes back like this:
{"d":{"success":true,"agency":[]}}
It crashes, I know my if statement is wrong but I dont know the correct method to make this work.
Just check the value before getting the object:
NSArray *agencyItem = [results objectForKey:#"agency"];
if ([agencyItem count] > 1)
{
codeItem = [agencyItem objectAtIndex:1];
}

Resources