TableView from JSON file - sort data - ios

Hi everyone I'm working with a JSON file to populate a UITableView.
The JSON file has two fields that I need to use:
- "First name"
- "region"
The "region" fields must be assigned for the creation of the UITableView sections.
The "name" fields must be sorted according to the section.
JSON File :
{
"Università" : [
{
"nome" : "Università degli Studi di Trento",
"regione" : "Trentino Alto Adige"
},
{
"nome" : "Università per Stranieri di Reggio Calabria \"Dante Alighieri\"",
"regione" : "Calabria"
},
{
"nome" : "Università degli Studi Suor Orsola Benincasa",
"regione" : "Campania"
},
{
"nome" : "Università degli Studi della Calabria ",
"regione" : "Calabria"
},
{
"nome" : "Università degli Studi di Napoli \"L'Orientale\"",
"regione" : "Campania"
}
]
}
As you can see from the JSON file, each "name" has a "region" so they must be sorted that way for example
(section) region 1
(cell) name with region 1
(cell) name with region 1
(cell) name with region 1
(section) region 2
(cell) name with region 2
(cell) name with region 2
(cell) name with region 2
How can I implement this to populate my UITableView?
This is the implementation I have done so far
-(void)retrieveUniversityListFromJSONFile {
/* Interpelliamo il file JSON all'interno del progetto per ottenere i nomi di tutte le università attualmente presenti nel file */
// Nome del file JSON
NSString *JSONFileName = #"university";
NSString *path = [[NSBundle mainBundle] pathForResource:JSONFileName ofType:#"json"];
NSData *data = [NSData dataWithContentsOfFile:path];
// Creazione di un dizionario che eredita informazioni dal file JSON
NSDictionary *JSONDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
// Inizializziamo l'array per prepararla ad accogliere i dati
_universityList = NSMutableArray.new;
for (NSDictionary *dict in JSONDict[#"Università"]) {
// Otteniamo i nomi delle università presenti nel file
NSString *universityName = dict[#"nome"];
// Otteniamo i nomi delle regioni italiane
NSString *regionName = dict[#"regione"];
// Aggiungiamo i risultati per le regioni all'array || _regionList ||
[_regionList addObject:regionName];
// Aggiungiamo i risultati all'array || _universityList||
[_universityList addObject:universityName];
}
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return _regionList.count;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return _universityList.count;
}

You need to manipulate the JSON data into an array that can be referenced by the table view's index path. The structure could be an array of dictionaries with each dictionary holding the region, and the list of names associated. You would need to iterate the JSON data and build a new array of dictionaries, adding one for each new region encountered, then adding the name to the array of names in that region's dictionary. Your index path section and row would reference the dictionary and index of the names respectively.
Your function might look like this:
_regionList = [NSMutableArray array];
for (NSDictionary *dict in JSONDict[#"Università"]) {
// Otteniamo i nomi delle università presenti nel file
NSString *universityName = dict[#"nome"];
// Otteniamo i nomi delle regioni italiane
NSString *regionName = dict[#"regione"];
BOOL found = NO;
for (NSDictionary *regDict in _regionList) {
if ([regDict[#"region_name"] isEqualToString:regionName]) {
//Region exists already
found = YES;
if (regDict[#"names"] == nil) {
//name array does not exist, create new array
regDict[#"names"] = [NSMutableArray arrayWithObject:universityName];
} else {
//name array does exist
regDict[#"names"] addObject:universityName];
}
break;
}
if (found == NO) {
//Region does not exist, create new region dictionary
NSMutableDictionary *newRegionDict = [NSMutableDictionary new];
newRegionDict[#"region_name"] = regionName;
newRegionDict[#"names"] = [NSMutableArray arrayWithObject:universityName];
}
}
Example of above data structure:
[
[0]: { "region_name": "Calabria",
"names": [
[0]: "Università per Stranieri di Reggio Calabria \"Dante Alighieri\"",
[1]: "Università degli Studi della Calabria"
]
},
[1]: { "region_name": "Campania",
"names": [
[0]: "Università degli Studi di Napoli \"L'Orientale\"",
[1]: "Università degli Studi Suor Orsola Benincasa"
]
}
]
The number of rows in section would be [_regionList[section][#"names"] count];
Your -(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section might look like this:
...
NSDictionary *region = _regionList[section];
NSString *regionName = _regionList[#"region_name"];
return regionName;
Your -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath:
...
NSDictionary *region = _regionList[indexPath.section];
NSString *uniName = _regionList[#"names"][indexPath.row];
...
Don't forget to call [yourTableView reloadData] after manipulating data referenced by the table.

Related

Objective C - Issue when read JSON Key

Hi everyone I am working with a JSON file in my xCode project.
I can easily display the various JSON key but when I call a key it specifies my app crashes and I don't understand why ...
I was very careful to write the keys correctly but it keeps crashing ...
This is my example JSON file
{
"Università" : {
"uniID" : {
"latitudine" : 43.115441,
"longitudine" : 12.389587,
"nome" : "Università per stranieri di Perugia",
"regione" : "Umbria"
},
"uniID" : {
"latitudine" : 41.860348,
"longitudine" : 12.496308,
"nome" : "Università degli Studi Internazionali di Roma ( UNINT )",
"regione" : "Lazio"
},
}
}
When I try to recover the "name" key my app crashes, this is true even if I call "latitude" or "longitude" etc ...
Where am I doing wrong ?
These are the functions I use for reading the JSON file
-(void)setupUniversityLocation:(MKMapView *)mapView {
NSDictionary *dict = [self JSONUniversity];
NSArray *universityArray = [[dict objectForKey:#"Università"] objectForKey:#"uniID"];
for (NSDictionary *uni in universityArray) {
NSString *uniname = [uni objectForKey:#"nome"];
NSLog(#"uniname %#",uniname);
}
}
#pragma mark - Read JSON Data University
-(NSDictionary *)JSONUniversity {
NSString *path = [[NSBundle mainBundle] pathForResource:#"university" ofType:#"json"];
NSData *data = [NSData dataWithContentsOfFile:path];
return [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
}
I also wanted to ask you how can I directly read the keys "name", "latitude" etc ... without where to invoke the "uniID" key? is it possible to bypass a category key?
There is no array in your json file. You should change json file to
{
"Università" : [
{
"latitudine" : 43.115441,
"longitudine" : 12.389587,
"nome" : "Università per stranieri di Perugia",
"regione" : "Umbria"
},
{
"latitudine" : 41.860348,
"longitudine" : 12.496308,
"nome" : "Università degli Studi Internazionali di Roma ( UNINT )",
"regione" : "Lazio"
}
]
}
Use [] to present array instead of {} and below code will work
-(void)setupUniversityLocation:(MKMapView *)mapView {
NSDictionary *dict = [self JSONUniversity];
NSArray *universityArray = [dict objectForKey:#"Università"];
for (NSDictionary *uni in universityArray) {
NSString *uniname = [uni objectForKey:#"nome"];
NSLog(#"uniname %#",uniname);
}
}
#pragma mark - Read JSON Data University
-(NSDictionary *)JSONUniversity {
NSString *path = [[NSBundle mainBundle] pathForResource:#"university" ofType:#"json"];
NSData *data = [NSData dataWithContentsOfFile:path];
return [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
}
There is no Array in the example JSON you posted.
So in this line:
NSArray *universityArray = [[dict objectForKey:#"Università"] objectForKey:#"uniID"];
When you are assuming the output is an array, in actuality it's a dictionary.
If you put a log statement outputting the kind of class returned after that line:
NSLog(#"Kind of class returned from univeristyArray = %#", [universityArray class]);
It will return:
Kind of class returned from univeristyArray = __NSDictionaryI
Right now your structure of the JSON example you posted is:
Top Level Object (Dictionary)
"Università" (Dictionary)
"uniID" (Dictionary)
Another issue with this structure is that you have multiple values for the same key under the "Università" dictionary (i.e. multiple "uniID" which have different associated values)
If you have control over the JSON generated, you have a couple of different options depending on what you're attempting to do:
From your code, it looks like you're attempting to loop through all the "Università" and output their name -- and you're expecting them to be stored in an Array. In this case you'd want to change the "Università" data structure to an Array in the JSON.
Alternatively, make the "nome" value of the university the key for the lower level dictionaries and then fetch them by name (only if the universities names are going to be unique) -- this would be good if you have a large list of universities and you're attempting to only fetch specific ones (by name).
Example of #1:
university.json:
{
"Università" : [
{
"latitudine" : 43.115441,
"longitudine" : 12.389587,
"nome" : "Università per stranieri di Perugia",
"regione" : "Umbria"
},
{
"latitudine" : 41.860348,
"longitudine" : 12.496308,
"nome" : "Università degli Studi Internazionali di Roma ( UNINT )",
"regione" : "Lazio"
},
]
}
setupUniversityLocation:
-(void)setupUniversityLocation {
NSDictionary *dict = [self JSONUniversity];
NSArray *universityArray = [dict objectForKey:#"Università"];
for (NSDictionary *uni in universityArray) {
NSString *uniname = [uni objectForKey:#"nome"];
NSLog(#"uniname %#",uniname);
}
}
Example of #2:
university.json:
{
"Università" : {
"Università per stranieri di Perugia": {
"latitudine" : 43.115441,
"longitudine" : 12.389587,
"regione" : "Umbria"
},
"Università degli Studi Internazionali di Roma ( UNINT )": {
"latitudine" : 41.860348,
"longitudine" : 12.496308,
"regione" : "Lazio"
},
}
}
setupUniversityLocation:
-(void)setupUniversityLocation {
NSDictionary *dict = [self JSONUniversity];
NSDictionary *universityDictionary = [dict objectForKey:#"Università"];
// this is an example of looping through the entire dictionary
// typically you'd use objectForKey when accessing a specific university
for (NSString *universityNameKey in universityDictionary.allKeys) {
NSDictionary *specificUniDictionary = [universityDictionary objectForKey:universityNameKey];
NSLog(#"uniname %#",universityNameKey);
NSLog(#"latitudine %#", [specificUniDictionary objectForKey:#"latitudine"]);
NSLog(#"longitudine %#", [specificUniDictionary objectForKey:#"longitudine"]);
}
}
For most cases I would recommend going with the second option as if it's a large list it's going to be a lot quicker to find a specific item, but it definitely depends on your use case.

How to sort a jSON file alphabetically and assign them to the corresponding letter to use sectionIndexTitlesForTableView/ sectionForSectionIndexTitle

This is my first time asking a question here, so please excuse my lack of writing etiquette.
I have a jSON data file which looks like this:
[ {
"category": "Feline",
"text": "CAT",
"definition": "Meow" },
{
"category": "Mammal",
"text": "DOG",
"definition": "Bark" },
{
"category": "Insect",
"text": "ANT ",
"definition": "buzz" },
{
"category": "Insect'",
"text": "MOSQUITO ",
"definition": "buzz" },
{
"category": "Number'",
"text": "10",
"definition": "ten" }
]
I am importing it as follows, the dataList is a NSMutableArray, I am also confused if using the MutableArray is good or if I should be using NSDictionary?:
-(void)readDataFromFile {
NSString * filePath =[[NSBundle mainBundle] pathForResource:#"data" ofType:#"json"];
NSError * error;
NSString* fileContents =[NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:&error];
if(error)
{
NSLog(#"Error reading file: %#",error.localizedDescription);
}
self.dataList = (NSMutableArray *)[NSJSONSerialization
JSONObjectWithData:[fileContents dataUsingEncoding:NSUTF8StringEncoding]
options:0 error:NULL];
}
I would like to sort the JSON data alphabetically according to 'text'
and also I am using sections and index list. I mainly followed https://www.appcoda.com/ios-programming-index-list-uitableview/ tutorial.
I am confused on how to sort the JSON data and also divide them into sections of alphabets and also iOS contacts accounts for numbers by putting them under '#' section.
How do i accomplish that as well?
Thanks in advance!
In the below code i've made an 2D array of 27 elements(1 for numeric
and 26 for alphabets) and then placed the value according to the
string initial character. This piece of code worked for me.Hope so it
will work for you too :)
for (int section = 0; section < 27; section++)
{
[arrSections addObject:[NSMutableArray array]];
}
for (NSDictionary *item in SampleDictionary)
{
NSString *KeyValue = [item[#"DictionaryKEy"] capitalizedString];
*//In your case its Text*
int ascii = (int)[KeyValue characterAtIndex:kZero];
if (ascii >= 65 && ascii <= 90)
{
[arrSections[(ascii - 64)] addObject:item];
}
else
{
[arrSections[0] addObject:item];
}
}

how to call for json with conditions in ios 9, using objective C

This is my json web response response.
-Itinerary: [
-{
ID: "1",
ValueOne: "2473.05",
ValueTwo: "368.95"
},
-{
ID: "2",
ValueOne: "2453.05",
ValueTwo: "308.95"
}
],
-Details :[
-{
ID:"1",
FirstName:"Graham",
LastName:"Json"
},
-{
ID:"1",
FirstName:"Anuradh",
LastName:"Stackoverflow"
}
]
What should be the response object type.I do like this, is it correct or it does not matter whatever the type
NSDictionary *Results = (NSDictionary *)responseObject;
then I get the response.now what I want is to get itinerary details and
get the Details only where the itinerary ID is equal to Details ID .how can I do that.
NSArray *Itinerary = [Resulsts objectForKey=#"Itinerary"];
NSArray *Itinerary = [Resulsts objectForKey=#"Detailss"];
for(NSDictionary *itinry in Itinerary)
{
NSString *Iid = [itinry objectForKey="ID"];
NSString *ValOne = [itinry objectForKey="ValueOne"];
//like this I'm getting values
//then here I want to get all details which it's `itinerary` `ID` equal to `Details` `ID`.how can I do that.
}
then here I want to get all details which it's itinerary ID equal to Details ID.how can I do that.
Please try this code Hope it will work for you
NSArray *Itinerary = [Resulsts objectForKey=#"Itinerary"];
NSArray *dTinerary = [Resulsts objectForKey=#"Detailss"];
for(int i=0; i<Itinerary;i++)
{
NSString *iID=[[Itinerary objectAtIndex:i] objectForKey:#"ID"];
NSString *dID=[[dTinerary objectAtIndex:i] objectForKey:#"ID"];
if ([iID isEqualToString:dID])
{
// do your thinks here
NSLog(#"%#",[[Itinerary objectAtIndex:i] objectForKey:#"ValueOne"]);
// break;
}
// NSString *Iid = [itinry objectForKey="ID"];
// NSString *ValOne = [itinry objectForKey="ValueOne"];
//like this I'm getting values
//then here I want to get all details which it's `itinerary` `ID` equal to `Details` `ID`.how can I do that.
}

count dictionary with multiple keys in iOS

This is my JSON :
collections = {
items = (
{
nom = "automne-hiver-2012-2013";
},
{
nom = carbon;
},
{
nom = colors;
});
};
}
I access to my json like this:
int j=0;
NSString *collections=self.dictionaryMenu[#"collections"][#"items"][j][#"nom"];
I'm looking for count all the key "nom" who are in my JSON.
I try :
for (objectKey in self.dictionaryMenu.allKeys) {
count2 += [[self.dictionaryMenu objectForKey:objectKey] count];
NSLog(#"Anzahl: %d", count2);
}
NSString *counter = [NSString stringWithFormat:#"COUNT MENU (%d)", count2];
NSLog(#"%#",counter);
Unfortunately, it sends me 1 ( i think that's because there is only 1 "collections" in the JSON).
How can i count all the key "nom" ?
Try this:
NSArray *items = self.dictionaryMenu[#"collections"][#"items"];
NSUInteger count = 0;
for (NSDictionary *item in items) {
if (item[#"nom"]) {
count++;
}
}

How to parse JSON multi-array

I need to parse the JSON file provided by Google Maps API
Then i use the AFNetworkingRequestHow to get the JSON response.
I built this dictionary:
NSDictionary *jsonDict = (NSDictionary *) JSON;
NSArray *rows = [jsonDict objectForKey:#"rows"];
But now, how can i reach the first value field of duration tag?
JSON File to parse:
{
"destination_addresses" : [ "San Francisco, CA, USA", "Victoria, BC, Canada" ],
"origin_addresses" : [ "Vancouver, BC, Canada", "Seattle, WA, USA" ],
"rows" : [
{
"elements" : [
{
"distance" : {
"text" : "1,527 km",
"value" : 1527251
},
"duration" : {
"text" : "15 hours 0 mins",
"value" : 54010
},
"status" : "OK"
},
{
"distance" : {
"text" : "112 km",
"value" : 111906
},
"duration" : {
"text" : "3 hours 1 min",
"value" : 10885
},
"status" : "OK"
}
]
}
}
Try
NSDictionary *jsonDict = (NSDictionary *) JSON;;
NSArray *rows = jsonDict[#"rows"];
NSDictionary *row = rows[0];
NSArray *elements = row[#"elements"];
NSDictionary *element = elements[0];
NSDictionary *duration = element[#"duration"];
NSInteger value = [duration[#"value"] integerValue];
[json objectForKey:#"elements"]
is an NSArray. You can't initialize an NSDictionary directly with an array.
(in JSON, { and } denote key-value pairs, like NSDictionary, whereas [ and ] delimit ordered lists like NSArray, that's why the mapping is done as it is...)
Following thinks can you understanding for development time so it may help lot.
You can use the following code:
NSString *valueString = [[[[[rows objectAtindex:0]objectForKey:#"elements" ]objectAtindex:0]objectForKey:#"duration"] objectForKey:#"value"];
//if you want integer value
NSInteger value = [valueString integerValue];

Resources