I am sorting my tableview by Distributor using the code below (it was Alphabetical by product)
NSSortDescriptor *aSort =[[NSSortDescriptor alloc] initWithKey:#"Dis" ascending:YES];
[distribArray sortUsingDescriptors:[NSMutableArray arrayWithObject:aSort]];
NSLog( #"data from table %#", distribArray);
[self.tableView reloadData];
NSLog(#"ok2222222222");
[[NSUserDefaults standardUserDefaults] setValue:#"Dis" forKey:#"ListBy"];
[[NSUserDefaults standardUserDefaults] synchronize];
I would like to know what the easiest way to display the Distributor name as a Title header above all the products for that Distributor. I currently display the Distributor name in the DetailsView of the cell for each product.
I would like to go from.
Product 1
Acme
Product 2
Acme
Product 3
Acme
To this below and keep my UITableView\Cells
Acme
Product 1
Product 2
Product 3
....
Many Thanks for any help.
maybe it is not the fastest way, but i think it is simple
first create a small inner class like this:
#interface ProductSection
#property (strong, nonatomic) NSString* sectionName;
#property (strong, nonatomic) NSMutableArray* products;
#end
then use this instead your sort:
NSSortDescriptor *aSort =[[NSSortDescriptor alloc] initWithKey:#"Dis" ascending:YES];
NSArray* products = [distribArray sortUsingDescriptors:[NSMutableArray arrayWithObject:aSort]];
self.sections = [NSMutableArray array];
NSString* currentDistributor = nil;
for (Product* p in products) {
if (![p.Dis isEqualToString:currentDistributor]) {
ProductSection* section = [[ProductSection alloc] init];
section.sectionName = p.Dis;
section.products = [NSMutableArray array];
[self.sections addObject:section];
currentDistributor = p.Dis;
}
ProductSection* section = [self.sections lastObject];
[section.products addObject:p];
}
[self.tableView reloadData];
where self.sections is a mutable array of ProductSection
next use this in your Table View Data Source:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [[[self.sections objectAtIndex:section] products] count];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [self.sections count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
[[self.sections objectAtIndex:section] sectionName];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
Product* p = [[[self.sections objectAtIndex:indexPath.section] products] objectAtIndex:indexPath.row];
...
}
hope that will help
Related
i use below code to binding tableview cell by "contacts" entity
- (NSManagedObjectContext *)managedObjectContext
{
NSManagedObjectContext *context=nil;
id delegate=[[UIApplication sharedApplication]delegate];
if ([delegate performSelector:#selector(managedObjectContext)])
{
context=[delegate managedObjectContext];
}
return context;
}
- (void)viewDidAppear:(BOOL)animated
{
//fetching contact into tableview
NSManagedObjectContext *moc=[self managedObjectContext];
totalFetch=[[NSFetchRequest alloc]initWithEntityName:#"Contacts"];
// 4 - Sort it if you want
totalFetch.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES selector:#selector(localizedCaseInsensitiveCompare:)]];
_contacts=[[moc executeFetchRequest:totalFetch error:nil]mutableCopy];
[self.myTable reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//create and initializetion cell
static NSString *cellIdentifier=#"cell";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
NSManagedObject *contact=[_contacts objectAtIndex:indexPath.row];
//implementing tableViewCells with Contact attribs
[cell.textLabel setText:[NSString stringWithFormat:#"%#",[contact valueForKey:#"name"]]];
[cell.detailTextLabel setText:[contact valueForKey:#"phoneNum"]];
UIImage *image = [UIImage imageWithData:[contact valueForKey:#"photo"]];
[cell.imageView setImage:image];
return cell;
}
now i want to add index and section to mytableview by first letter of "name" field in "contacts" entity, Please put your answers according to my code, thanks
You need to implement the following datasource methods for UITableView:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
The first two are standard and implement the cells that are going to be displayed in the table view.
The third one is the number of sections the table view should be divided up into. For something like this I would use an 'alphabet array' i.e. an array with all the letters of the alphabet in e.g.:
NSMutableArray *alphabetArray = [[NSMutableArray alloc] init];
for (int i = 0; i < 26; i++) {
char letter = 'A';
letter += i;
[alphabetArray addObject:[NSString stringWithFormat:#"%c", letter]];
}
You can return alphabetArray.count for the third datasource method.
The fourth method requests the section number for the section title, all you need to do here is return: [alphabetArray indexOfObject:title];.
The fifth method is asking for the title for a specific section so you can return: alphabetArray[section]; here.
Finally the sixth method is asking for all the titles in an array so you can just return alphabetArray here .
In order to get the number of rows in a section you need to break down your contacts array by starting letter. To do this you can use predicates e.g.
NSString *letter = alphabetArray[indexPath.section];
NSArray *filteredContacts = [contacts filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"name BEGINSWITH[cd] %#", letter]];
return filteredContacts.count;
You can apply the same logic to get the contact to display in a cell:
NSString *letter = alphabetArray[indexPath.section];
NSArray *filteredContacts = [contacts filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"name BEGINSWITH[cd] %#", letter]];
Contact *contact = filteredContacts[indexPath.row];
Hope this helps.
I created a table with sections. Each section has a date (2014-03-23) as a title and under each date I want to populate a list of games to be played that day. When I run the app the table gets the section title fine (date of game), but every section has the same matches list. I want to have the games match under the section date.
I know i need to include indexPath.section in the CellForRowsAtIndexPath but I'm having a hard time figuring it out.
Here's my code:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return gamesArray.count;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
uniqueArray = [[NSOrderedSet orderedSetWithArray:dateSection] array];
return [uniqueArray count];
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [self.dateSection objectAtIndex:section];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//NSString *CellIdentifier = [NSString stringWithFormat:#"games cell-%ld-%ld", (long)indexPath.section, (long)indexPath.row];
static NSString *CellIdentifier = #"games cell";
//NSString *CellIdentifier = [NSString stringWithFormat:#"cell-%d-%d", indexPath.section, indexPath.row];
CustomInboxCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = (CustomInboxCell *)[[CustomInboxCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
PFObject *post = [gamesArray objectAtIndex:indexPath.row];
[cell.teamsLabel setText:[post objectForKey:#"teams"]];
[cell.liveRepeatLabel setText:[post objectForKey:#"liveRepeat"]];
[cell.gameTimeLabel setText:[post objectForKey:#"gameTime"]];
return cell;
}
Any help would be greatly appreciated.
//======================================================
//I decided to use a predicate to filter and get the number of items per date(Number of games per date)
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSString *sectionTitle = [uniqueArray objectAtIndex:section];
if (section >=0) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"gameDate == %#",sectionTitle];
NSLog(#"section name = %#", sectionTitle);
NSArray *filtered = [gamesArray filteredArrayUsingPredicate:predicate];
NSLog(#"filtered = %#",filtered);
return filtered.count;
}
return 0;
}
//I just need to iterate through every date and return the number of games per date. Any suggestions?
You need a separate array for each section of the table. In numberOfRowsForSection, you need to return a count for the array that corresponds to the given section.
Here's an example. The data for the table is stored in an NSArray called tableData. The array has one entry for each section of the table. Each entry in tableData is an NSDictionary. The NSDictionary has two keys, title and items. The title key corresponds to an NSString that serves as the title for the table section. The items key corresponds to an NSArray that has the row information for the table section.
The table is organized into two sections like this
Fruits
Apples
Oranges
Animals
Dog
Cat
Horse
Cow
Here's the code
#import "MainViewController.h"
#interface MainViewController () <UITableViewDataSource, UITableViewDelegate>
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#property (strong, nonatomic) NSArray *tableData;
#end
#implementation MainViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.dataSource = self;
self.tableView.delegate = self;
NSDictionary *fruits, *animals;
fruits = #{ #"title" : #"Fruits" , #"items" : #[#"Apples", #"Oranges"] };
animals = #{ #"title" : #"Animals", #"items" : #[#"Dog", #"Cat", #"Horse", #"Cow"] };
self.tableData = #[fruits, animals];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return( self.tableData.count );
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSDictionary *sectionData = self.tableData[section];
NSArray *items = sectionData[#"items"];
return( items.count );
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSDictionary *sectionData = self.tableData[section];
NSString *title = sectionData[#"title"];
return( title );
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"SomeCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSDictionary *sectionData = self.tableData[indexPath.section];
NSArray *items = sectionData[#"items"];
NSString *name = items[indexPath.row];
cell.textLabel.text = name;
return cell;
}
#end
This is a data set problem, you need to have a separate dataset prepared for each section of your tableview and iterate them using the index path (row, section) properties in your cellForRowAtIndexPath method. If you can do NSLog and share your dataset, it would be more helpful to answer accurately. Hope this helps.
Really stumped with this need some help! I'm creating a subclass of a UITableViewController to display a list of FB Friends (FBFriendPickerViewController has several limitations for me). I'm able to retrieve an array of id and sort them alphabetically.
However, still can't figure out a way from here to create a separate dictionary to section the FB users into alphabetical sections for indexing.
-(void)captureFacebookFriendUsers
{
//Issue a Facebook Graph API request
NSLog(#"%#", NSStringFromSelector(_cmd));
[FBRequestConnection startForMyFriendsWithCompletionHandler:^(FBRequestConnection *connection, id result, NSError *error){
if (!error) {
NSLog(#"No error requesting friends");
friendsObjects = [result objectForKey:#"data"]; //Objects are id<FBGraphUser>
friendsNames = [NSMutableArray arrayWithCapacity:friendsObjects.count];
NSMutableArray *friendIds = [NSMutableArray arrayWithCapacity:friendsObjects.count];
//Create a list of friends' Facebook IDs
NSSortDescriptor *firstNameDescriptor = [[NSSortDescriptor alloc]initWithKey:#"first_name" ascending:YES];
friendsObjects = [friendsObjects sortedArrayUsingDescriptors:#[firstNameDescriptor]];
for (NSDictionary *friendObject in friendsObjects) {
[friendIds addObject:[friendObject objectForKey:#"id"]];
[friendsNames addObject:[friendObject objectForKey:#"first_name"]];
}
}
Thanks for taking time to read through this!
Andris's code is excellent, but you don't need to create a separate Person class for this to work. Simply use NSDictionary in place of Person class as follows:
First, create your dictionary - I do this in the View Controller from which I am about to call the table view as part of my button action. You'll also need to declare an NSArray *friends and an NSNumber *friendsCount property in both of your .h files (for your initial view controller and for your table view controller) and synthesize as _friends _friendCount.
- (IBAction)btnAddFriendsTapped:(UIBarButtonItem *)sender {
if (FBSession.activeSession.isOpen){
__block NSArray *friendsArray = [[NSArray alloc]init];
__block NSNumber *friendsArrayCount = [[NSNumber alloc]init];
FBRequest* friendsRequest = [FBRequest requestForMyFriends];
[friendsRequest startWithCompletionHandler: ^(FBRequestConnection *connection,
NSDictionary* result,
NSError *error) {
friendsArray = [result objectForKey:#"data"];
friendsArrayCount = [NSNumber numberWithInt:friendsArray.count];
NSLog(#"Found: %i friends", [friendsArrayCount intValue]);
for (NSDictionary<FBGraphUser>* friend in friendsArray) {
NSLog(#"I have a friend named %# with id %#", friend.name, friend.id);
_friends = [NSArray arrayWithArray:friendsArray];
_friendCount = [NSNumber numberWithInt:[friendsArrayCount intValue]];
}
[self performSegueWithIdentifier:#"friendListSegue" sender:self];
}];
}
Then in the prepareForSegue method pass your dictionary to the Table View Controller not forgetting to import your table view controller header file first.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"friendListSegue"]){
BJFriendListTVC* listOfFriends = segue.destinationViewController;
listOfFriends.friends = _friends;
listOfFriends.friendCount = _friendCount;
}
}
Finally, taking Andris's table code replace the Person class
// Put friends into the appropriate sections
for (NSDictionary<FBGraphUser> *friend in self.friends) {
// Ask the collation which section number the friend name belongs in
NSInteger sectionNumber = [self.collation sectionForObject:friend collationStringSelector:#selector(name)];
// Get the array for that section.
NSMutableArray *sectionFriends = [newSectionsArray objectAtIndex:sectionNumber];
// Add the friend to the section.
[sectionFriends addObject:friend];
}
then when you configure the cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSDictionary<FBGraphUser> *person = [[self.sectionsArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
cell.textLabel.text = person.name;
return cell;
}
You'll need to use UILocalizedIndexedCollation for this and call [self.collation sectionForObject:friend collationStringSelector:#selector(name)] to get the index of the section that corresponds to friend name for the locale of the device.
To do that you'll need to store the friend data in a class that has a property "name" (there might be a way to keep using NSDictionary for friend data that I am not aware of).
Here is some code:
// View Controller code
- (void)viewDidLoad
{
[super viewDidLoad];
[self condigureSections];
}
- (void)configureSections
{
// UILocalizedIndexedCollation
self.collation = [UILocalizedIndexedCollation currentCollation];
NSInteger index, sectionTitlesCount = [[self.collation sectionTitles] count];
// new sections with data
NSMutableArray *newSectionsArray = [[NSMutableArray alloc] initWithCapacity:sectionTitlesCount];
// allocate data array for each of the sections
for (index = 0; index < sectionTitlesCount; index++) {
NSMutableArray *array = [[NSMutableArray alloc] init];
[newSectionsArray addObject:array];
}
// Put friends into the appropriate sections
for (Person *friend in self.friends) {
// Ask the collation which section number the friend name belongs in
NSInteger sectionNumber = [self.collation sectionForObject:friend collationStringSelector:#selector(name)];
// Get the array for that section.
NSMutableArray *sectionFriends = [newSectionsArray objectAtIndex:sectionNumber];
// Add the friend to the section.
[sectionFriends addObject:friend];
}
// Now that all the data's in place, each section array needs to be sorted.
for (index = 0; index < sectionTitlesCount; index++) {
NSMutableArray *friendsArrayForSection = [newSectionsArray objectAtIndex:index];
NSArray *sortedFriendsArrayForSection = [self.collation sortedArrayFromArray:friendsArrayForSection collationStringSelector:#selector(name)];
// Replace the existing array with the sorted array.
[newSectionsArray replaceObjectAtIndex:index withObject:sortedFriendsArrayForSection];
}
self.sectionsArray = newSectionsArray;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [self.sectionsArray count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [[self.collation sectionTitles] objectAtIndex:section];
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
return [self.collation sectionIndexTitles];
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
return [self.collation sectionForSectionIndexTitleAtIndex:index];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[self.sectionsArray objectAtIndex:section] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
....
Person *person = [[self.sectionsArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
....
cell.textLabel.text = person.name;
....
return cell;
}
// Store friend data in a class Person so that we could pass the object to
// - (NSInteger)sectionForObject:(id)object collationStringSelector:(SEL)selector
// Example Person.h
#interface Person : NSObject
#property (nonatomic, copy) NSString *id;
#property (nonatomic, copy) NSString *name;
#property (nonatomic, copy) NSString *pictureUrl;
- (id)initWithId:(NSString *)id name:(NSString *)name picture:(NSString *)picUrl;
#end
in my app the user adds cells to a tableView using coreData. This works quite well. But now I want the table view to have sections.
The viewController in which you add new cells look like:
#property (strong) NSManagedObject *travel;
...
-(void)viewDidLoad{
countryName = [[NSArray alloc] initWithObjects:
#"USA", #"England", #"Italy", nil];
countryLabel.text= [countryName objectAtIndex:[picker selectedRowInComponent:0]];
}
- (IBAction)save:(id)sender {
[self.travel setValue:countryLabel.text forKey:#"country"];
}
and in the viewController which displays the cells in a tableView:
#property (strong) NSMutableArray *travelAll;
...
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSPredicate *predicate=[NSPredicate predicateWithFormat:#"position == %#",_positionString];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Travel"];
[fetchRequest setPredicate : predicate ];
self.travelAll = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
[self.tableView reloadData];
...
- (NSString *)tableView:(UITableView *)tableView
titleForHeaderInSection:(NSInteger)section
{ NSArray* headers = [NSArray arrayWithObjects:#"USA",#"England","Italy",nil];
return [headers objectAtIndex:section];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 3;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.travelAll count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSManagedObject *travel = [self.travelAll objectAtIndex:indexPath.row];
...
return cell;
}
But now my tableView I have just this three sections (headers) but I can't add cell to them.
For example: the user selects USA for his new cell, so this cell should be displayed in the section USA
Your datasource methods are flawed. For example, you are returning the same cell data for each section. There are other problems as well.
It is much better to use a NSFetchedResultsController. Start from the Apple templates (you get that if you create a new project and choose "Use Core Data"), that employ the fetched results controller.
Your section design becomes very simple then: it is enough to simply specify the sectionNameKeyPath property.
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.