I started develop an app which is using WCF service with JSON data. I got the data from WCF service but I didn't use it as I want.
here is the JSON data:
{"MenuDoldurAndroidResult":[
{"menu_description":"Turkish Pizza","menu_title":"L Pizza","menu_price":"26 TL"},{"menu_description":"Italiano Pizza","menu_title":"L Pizza","menu_price":"27 TL"},{"menu_description":"Extravaganza","menu_title":"L Pizza","menu_price":"29 TL"},{"menu_description":"Pepporoni Pizza","menu_title":"L Pizza","menu_price":"28 TL"},{"menu_description":"Turkish Pizza","menu_title":"S Pizza","menu_price":"12 TL"},{"menu_description":"Italiano Pizza","menu_title":"S Pizza","menu_price":"13 TL"},{"menu_description":"Extravaganza","menu_title":"S Pizza","menu_price":"15 TL"},{"menu_description":"Pepporoni Pizza","menu_title":"S Pizza","menu_price":"14 TL"}
]}
What I want:
If there are 2 title here, there must be 2 section in table view. Every item must be in their section.
Like this:
-L Pizzas
Turkish Pizza 26 TL
Italiano Pizza 27 TL
Extravaganza Pizza 29 TL
Pepperoni Pizza 28 TL
-S Pizzas
Turkish Pizza 12 TL
Italiano Pizza 13 TL
Extravaganza Pizza 15 TL
Pepperoni Pizza 14 TL
How can I access this item and display like this ?
- (void)viewDidLoad
{
[super viewDidLoad];
//I posted request to service here. I didn't write these parts of code.
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:data
options:NSJSONReadingMutableContainers
error:&error];
NSMutableArray *array= [json objectForKey:#"MenuDoldurAndroidResult"];
menu = [[NSMutableArray alloc] initWithCapacity:3];
NSString *descriptionTemp;
NSString *titleTemp;
NSString *priceTemp;
for(int i=0; i< array.count; i++)
{
NSDictionary *menuList= [array objectAtIndex:i];
titleTemp = [menuList objectForKey:#"menu_title"];
descriptionTemp = [menuList objectForKey:#"menu_description"];
priceTemp = [menuList objectForKey:#"menu_price"];
[menu addObject:[NSArray arrayWithObjects:titleTemp,descriptionTemp,priceTemp,nil]];
}
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 2;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 2;
}
-(NSString *)tableView:(UITableView*)tableView titleForHeaderInSection:(NSInteger)section{
if (section==0) {
return #"L Pizzas";
}
else{
return #"S Pizzas";
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:nil];
cell.textLabel.text = [menu objectAtIndex: indexPath.row];
return cell;
}
If your content is static you can try using the answer by Sunny. But if is dynamic it's better to store the data in a different way. Obviously L pizza and S pizza seems to be a category and the rest are like category items.
You need to make a collection of the categories. Demo Project Source Code
- (void)viewDidLoad
{
[super viewDidLoad];
//I posted request to service here. I didn't write these parts of code.
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:data
options:NSJSONReadingMutableContainers
error:&error];
NSMutableArray *allPizzas = [json[#"MenuDoldurAndroidResult"] mutableCopy];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"menu_price"
ascending:YES
selector:#selector(compare:)];
[allPizzas sortUsingDescriptors:#[sortDescriptor]];
NSMutableArray *pizzaCategories = [#[]mutableCopy];
//Find unique categories in all the pizzas
NSSet* categories = [NSSet setWithArray: [allPizzas valueForKey:#"menu_title"]];
//Enumerate to form a new reformatted category array
for (NSString *categoryTitle in categories)
{
//Predicate is used to find the items that come under current category
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"menu_title == %#",categoryTitle];
NSArray *categoryItems = [allPizzas filteredArrayUsingPredicate:predicate];
//New dictionary with name of category and category items are formed
NSDictionary *categoryDict = #{#"menu_title":categoryTitle,#"pizzas":categoryItems};
[pizzaCategories addObject:categoryDict];
}
//Assign the new formatted category array to the instance variable for holding categories.
self.categories = pizzaCategories;
}
Modify the datasource of tableView for the new structure
#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
//The count of categories will give number of sections
NSUInteger sections = [self.categories count];
return sections;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//The number of items in a category is calculated
NSDictionary *category = self.categories[section];
return [category[#"pizzas"] count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
//Title for the category
NSDictionary *category = self.categories[section];
return category[#"menu_title"];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
NSDictionary *category = self.categories[indexPath.section];
NSArray *categoryItems = category[#"pizzas"];
NSDictionary *categoryItem = categoryItems[indexPath.row];
cell.textLabel.text = categoryItem[#"menu_description"];
cell.detailTextLabel.text = categoryItem[#"menu_price"];
return cell;
}
You can also use the free Sensible TableView framework to fetch the data from the web service and automatically display it in your table view.
Related
I have created a UITableView with custom cell & stored name,no,pincode in to these cell.
Here is my Code for array:-
for (int i =0; i<[tempArr count]; i++)
{
NSString *rawData = [tempArr objectAtIndex:i];
if (rawData !=nil)
{
Persons *newPerson = [[Persons alloc]init];
NSArray *data = [rawData componentsSeparatedByString:#"\t"];
newPerson.name = [NSString stringWithFormat:#"%#",[data objectAtIndex:0]];
newPerson.no = [[data objectAtIndex:1] integerValue];
newPerson.pincode = [[data objectAtIndex:2] integerValue];
[allPersons addObject:newPerson];
}
}
Here is my Customcell.h
#interface Customcell : UITableViewCell
#property(weak) Persons* person;
#end
UITableView Datasrouce method:-
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
Customcell *cell = [tblStations dequeueReusableCellWithIdentifier:#"personCell"];
if (tableView == self.searchDisplayController.searchResultsTableView)
{
cell.person = filteredContentList[indexPath.row];
[cell.textLabel setText:cell.person.name];
}
else
{
cell.person = allPersons[indexPath.row];
[cell.textLabel setText:cell.person.name];
}
return cell;
}
How do i create Section & index list for all names from A to Z & give title by cell.textLabel.text?
I am following This Tutorial but it has static keys & names added to NSDictionary,NSArray.
In my example i do not know how many names starting with same letter can come in the array. i am also using UISearchDisplayController for search person name.
I want to add number of sections & title for those sections by names that is in the array or cell.textLabel.text dynamically.
i do not know about UISearchDisplayController that these sections & index list will be displaying in UISearchDisplayController so i do not want these sections & index list while searching.
You need to spend a little more time trying to make your questions more clear.
Include a custom implementation of the necessary UITableView data source and delegate methods...
NOTE my assumption that your variable allPersons is an NSMutableArray.
NOTE these do not include for your search results data sets!
Return an NSInteger for the number of sections in your UITableView...
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
NSSet *setData = nil;
NSInteger integerData = 0;
setData = [NSSet setWithArray:allPersons];
integerData = [setData count];
return integerData;
}
UPDATE
Return an NSString for section header titles...
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSOrderedSet *setData = nil;
NSString *stringData = nil;
setData = [NSOrderedSet orderedSetWithArray:allPersons];
stringData = [[setData allObjects] componentsJoinedByString:#" "];
return stringData;
}
...plus others if I have the time...
I have been trying to set the uiTableViewHeader for my UITableView for a couple of days now with no luck. I don't think I am far off. Currently it shows the section Titles however multiples the number of records by X amount ( I presume my count may be wrong).
I think I need to further configure my cellForRowAtIndexPath method but Im unsure how.
I am a bit confused. I need to group the rowsAtIndexPath to the sections and stop them multiplying.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"atozCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
//Searchbar code is here
NSDictionary *dataDict = [self.sortedArray objectAtIndex:indexPath.section];
cell.textLabel.text = [dataDict objectForKey:#"Title"];
}
return cell;
}
Section Counts
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [self.sectionArray count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [self.sectionArray objectAtIndex:section];
}
Data Populated from
// Find out the path of recipes.plist
NSString *path = [[NSBundle mainBundle] pathForResource:#"law2" ofType:#"plist"];
// Load the file content and read the data into arrays
self.dataArray = [NSArray arrayWithContentsOfFile:path];
//Sort the array by section
self.sortedArray = [self.dataArray sortedArrayUsingDescriptors:#[
[NSSortDescriptor sortDescriptorWithKey:#"Section" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:#"Title" ascending:YES]]];
//Section for sorting
self.sectionArray = [self.sortedArray valueForKeyPath:#"Section"];
Always you are sending index of the object. So please try to use this one
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
return [self.tableDataIndexTitles objectAtIndex:index];
}
Developing a iPAD app, where I'm trying to populate table, This is how i'm doing:
In view did load, I'm creating two dictionary object and adding object as Pdf and Excel.
- (void)viewDidLoad
{
[super viewDidLoad];
arrDocuments = [[NSMutableArray alloc] init];
NSArray *arr1 = [NSArray arrayWithObjects:#"PDF", nil];
NSDictionary *pdf = [NSDictionary dictionaryWithObjects:arr1 forKeys:nil];
NSArray *arr2 = [NSArray arrayWithObjects:#"Excel", nil];
NSDictionary *excel = [NSDictionary dictionaryWithObjects:arr2 forKeys:nil];
[arrDocuments addObject:pdf];
[arrDocuments addObject:excel];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [arrDocuments count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
//return [arrReceipes count];
NSDictionary *dictionary = [arrDocuments objectAtIndex:section];
NSArray *array = [dictionary objectForKey:[self.sortedKeys objectAtIndex:section]];
return [array count];
}
-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"MyIdentifier";
UITableView *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell ==nil) {
cell = [[UITableViewCell alloc]initWithFrame:CGRectZero reuseIdentifier:MyIdentifier];
}
return cell;
}
With this implementation I'm not able to see table view.Its going to main method and showing me SIGABRT message.Where I'm going wrong??
While creating NSDictionary, you have passed nil in place of keys array,
NSDictionary *pdf = [NSDictionary dictionaryWithObjects:arr1 forKeys:nil];
You should give proper objects and keys to the dictionary. This method expects objects and keys to be given in an array as you can see in its method signature.
+ (instancetype)dictionaryWithObjects:(NSArray *)objects forKeys:(NSArray *)keys
I have some JSON data that I am getting from my database. I can pull it fine and load it into my table view. my issue is separating my JSON data so I can section the tableview.
JSON
[{"id":"1","name":"steve mans","phoneNumber":"(559)123-4455","showNumber":"1","greenCard":"1","expiration":"2014-02-15","driver":"1","paid":"1","watch":"1"},
{"id":"2","name":"myself and me","phoneNumber":"(559)321-6784","showNumber":"1","greenCard":"1","expiration":"2013-10-18","driver":"0","paid":"0","watch":"2"},
{"id":"4","name":"tod bellesmithson","phoneNumber":"(559)678-3421","showNumber":"0","greenCard":"1","expiration":"2013-11-22","driver":"1","paid":"0","watch":"2"},
{"id":"3","name":"John Smith","phoneNumber":"(559)123-1234","showNumber":"1","greenCard":"0","expiration":"2013-10-08","driver":"0","paid":"1","watch":"3"},
{"id":"5","name":"greg smith","phoneNumber":"559 345-1234","showNumber":"1","greenCard":"1","expiration":"2013-10-08","driver":"0","paid":"1","watch":"3"}]
What I am trying to do is, separate this data into three sections in my tableview. So I thought create three different tables and load each table into a different section of the tableview. But the information is the same in each one (id, name, phone etc.) So I ended up with one table and added a column that designates what shift people work, 'watch'. So how do I separate the data by using the watch column, so in my tableview i will have:
section one
people who work night shift
section two
people who work morning
section three
night shift
Try with this code:
NSArray *data = (NSArray)[NSJSONSerialization JSONObjectWithData:jsonData
options:NSJSONReadingMutableContainers
error:&error];
NSMutableArray *morningShift = [NSMutableArray array];
NSMutableArray *noonShift = [NSMutableArray array];
NSMutableArray *nightShift = [NSMutableArray array];
for (int i=0; i< [data count]; i++)
{
NSDictionary *item = data[i];
if (#"1" == item[#"watch"] )
{
[morningShift addObject:item];
} else if (#"2" == item[#"watch"] )
{
[noonShift addObject:item];
} else if (#"3" == item[#"watch"] )
{
[nightShift addObject:item];
}
}
try this
NSMutableArray *tableData = [NSMutableArray alloc] init];
NSArray* nameArr = [NSArray arrayWithObjects: #"1", #"2",#"3",nil];
for(int i=0; i<[nameArr count]; i++)
{
[tableData addObject:[jsonArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"watch = %#",[nameArr objectAtIndex:i]]] ];
}
TableView Delegate Methods
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [tableData count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[tableData objectAtIndex:section ] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell= nil;
//implement your logic to display the cell item;
NSArray sectionData = [tableData objectAtIndex:indexPath.section];
NSArray rowData = [sectionData objectAtIndex:indexPath.row];
return cell;
}
Please note i have not compiled the code. There is a chance of compilation error.
check for section in your cellForRowAtIndexPath method and load data accordingly,
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//initialize cell
if (indexPath.section == 0){
// load data
}
return cell;
}
I have a list of countries and venues read in by JSON. It now reads in correctly and seems to store relationships.
// Read JSON
NSString *jsonPath = [[NSBundle mainBundle] pathForResource:#"venues" ofType:#"json"];
NSData *data = [NSData dataWithContentsOfFile:jsonPath];
id json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
if (error) {
NSLog(#"Error - %#", error);
} else {
//NSLog(#"JSON = %#", json);
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
/*
"USA": [
{
"venue": "Von Braun Center",
"city" : "Huntsville",
"state": "Alabama",
"capacity": 13760
},
*/
for (NSDictionary *dict in json) {
NSString *name = (NSString *) [dict objectForKey:#"name"];
NSArray *venueList = (NSArray *) [dict valueForKey:#"venues"];
[MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *c) {
Country *country = [Country createInContext:c];
[country setName:name];
NSMutableArray *listOfVenues = [NSMutableArray array];
NSLog(#"Country - %#", country.name);
for (NSDictionary *venueData in venueList) {
NSString *name = (NSString *) [venueData objectForKey:#"venue"];
NSString *city = (NSString *) [venueData objectForKey:#"city"];
NSString *state = (NSString *) [venueData objectForKey:#"state"];
//NSNumber *capacity = (NSNumber *) [NSNumber numberWithInt:[[venueData valueForKey:#"capacity"] intValue]];
Venue *v = [Venue createInContext:c];
[v setName:name];
[v setCity:city];
[v setState:state];
[v setCountry:country];
[listOfVenues addObject:v];
NSLog(#"Venue - %#, %#", v.name, v.country.name);
} // next
[country setVenues:[NSSet setWithArray:listOfVenues]];
} completion:^{
}];
} // next
dispatch_async(dispatch_get_main_queue(), ^{
[[NSManagedObjectContext defaultContext] saveNestedContexts];
NSUInteger entities = [Venue countOfEntities];
NSLog(#"Venues saved = %d", entities);
});
});
} // end if
This produces a log of venues, like this;
Loading venue data...
Country - USA
Venue - Von Braun Center, USA
Venue - Birmingham Convention Center, USA
Country - UK
Venue - O2 Arena, UK
Venue - MEN Arena, UK
So far so good.
But when I get to the actual Venue view it simply displays the venues in alphabetical order but it does displays the section at their correct
My code is;
// viewDidLoad
self.fetchedResultsController = [Venue fetchAllGroupedBy:#"country.name" withPredicate:nil sortedBy:#"name" ascending:YES];
#pragma mark - Table View
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects];
}
-(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo name];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
Venue *v = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = v.name;
}
What this produces on the screen is the following;
I have tried resetting the app and its data to no avail.
Screenshot (via Imageshack)
As you can see, the list is just alphabetical and not correct and not split up across the relevant sections.
It seems to stem from the
Venue *v = [self.fetchedResultsController objectAtIndexPath:indexPath];
line but I am not sure how to fix it.
I am wondering what I am doing wrong and how I can fix it so that it is displaying the correct data in the correct section.
After setting the country for a venue
[v setCountry:country];
this line is redundant and might break your relationships
[country setVenues:[NSSet setWithArray:listOfVenues]];
You only have to set the relationship once. The reverse relationship is generated automatically.
I was able to put the sections in the right groups (ie: USA venues now belong to the USA country)
self.fetchedResultsController = [Venue fetchAllGroupedBy:#"country.name" withPredicate:nil sortedBy:#"country.name" ascending:YES delegate:self inContext:managedObjectContext];
But now what is happening is that the venues are not ordered by name ascending.
I get a list like this;
Screenshot:
http://img443.imageshack.us/img443/340/6f3o.png
The venues are now grouped to countries, but the venues themselves are not ordered in A-Z.
I would like my venues to be arranged in A-Z and the countries would not be ordered.
But I am not sure how to do this.