I have an indexed table view that organizes cities in a state by their first letter. What I have working is an NSMutableDictionary is created with the keys of A,B,C,etc. and the corresponding cities are added to their respective arrays. ex:
Y = (
Yatesboro,
Yeagertown,
York,
"York Haven",
"York New Salem",
"York Springs",
Youngstown,
Youngsville,
Youngwood,
Yukon
);
Z = (
Zelienople,
Zieglerville,
"Zion Grove",
Zionhill,
Zionsville,
Zullinger
);
now, my table view loads with the correct number of sections, and rows within the sections and the indexing control works fine with this:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [cities count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if([searchArray count]==0)
return #"";
return [searchArray objectAtIndex:section];
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [[cities objectForKey:[searchArray objectAtIndex:section]] count];
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
NSLog([NSString stringWithFormat:#"clicked index : %i",index]);
if (index == 0) {
[tableView scrollRectToVisible:[[tableView tableHeaderView] bounds] animated:NO];
return -1;
}
return index;
}
My issue is now populating the text of the table cell with the text for each section...Any thoughts on how I can grab this info?
the cellForRowAtIndexPath gets a parameter of type NSIndexPath passed which contains both the required row and section. See NSIndexPath UIKit Additions for more details.
With that being said, this might work in your particular case:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:cellIdentifier] autorelease];
}
NSString *letter = [searchArray objectAtIndex:indexPath.section];
NSArray *city = [cities objectForKey:letter];
cell.text = [city objectAtIndex:indexPath.row];
return cell;
}
Not sure if I got it right (haven't tried on a compiler), but you may get the general idea by now :)
Related
I'm currently creating a tableview with data from server. I have made it before, i copied over the code from the other files, but for some reason it's very strange. When i run the app, the tableview is empty and I found out that The cell.price.text is not updating, even though I hardcode it as #"123", cell.price.text is still showing null in NSLog.
I'm sure all these three method are called, because I put nslog in each of them
//TableView Setting
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
NSLog(#"Countdata %i",countdata);
return countdata;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ShopTableViewCell";
ShopTableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[ShopTableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
NSLog(#"hi");
}
// Configure the cell...
cell.price.text = [self.gprice objectAtIndex:[indexPath row]];
NSLog(#"Good,%#",[self.gprice objectAtIndex:[indexPath row]]);
NSLog(#"text,%#",cell.price.text);
return cell;
}
I have a tableview whose data are selected from a pickerView(3 columns).Here is the code:
- (void)viewDidLoad {
[super viewDidLoad];
//PickerView content and sort them for displaying
Number=#[#"Trans",#"2005",#"2006",#"2007",#"2008",#"2009",#"2010",#"2011",#"2012",#"2013",#"2014",#"2015",#"2016"];
Season=#[#"Spring",#"Summer",#"Fall"];
Course=#[#"CHEM1100 General Chem I",#"CHEM2100 General Chem II",#"CHEM3511 Org Chem",#"CHEM3521 Org Chem II"];
Course =[Course sortedArrayUsingSelector:#selector(compare:)];
Number =[Number sortedArrayUsingSelector:#selector(compare:)];
Season =[Season sortedArrayUsingSelector:#selector(compare:)];
_tableView.delegate = self;
_tableView.dataSource = self;
}
To populate the tableView, I use a button, when the button is pushed, the selection of pickerView will send data to tableView
- (IBAction)addCourse:(UIButton *)sender {
NSInteger numRow=[picker selectedRowInComponent:kNumComponent];//0=1st,1=2nd,etc
NSInteger SeaRow=[picker selectedRowInComponent:kSeaComponent];//0=fall,1=spring,2=summer
NSInteger CourseRow=[picker selectedRowInComponent:kCourseComponent];
NSString *num=Number[numRow];
NSString *season=Season[SeaRow];
NSString *course=Course[CourseRow];
NSString *CourseToAdd=[[NSString alloc ]initWithFormat:#"%# ",course];
NSString *SeasonToAdd=[[NSString alloc ]initWithFormat:#"%# ",season];
NSString *YearToAdd=[[NSString alloc ]initWithFormat:#"%# ",num];
[self.msgCourse addObject:CourseToAdd];
[self.msgSeason addObject:SeasonToAdd];
[self.msgYear addObject:YearToAdd];
[_tableView reloadData];
}
To show the data in tableView, I use
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if(!cell){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"Cell"];
}
cell.textLabel.text=[self.msgCourse objectAtIndex:indexPath.row];
return cell;
}
To determine the rows and sections
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
//return [self.msgYear count];
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [self.msgCourse count];
}
It is running fine. The output is shown in the picture attached.
Here are my questions:
(1) I want the tableView shown in more than one sections. For example, "2005 Fall" is one section, inside this section, the courses are shown. In other words, the first two columns selected in the pickerview will form the section title.
(2) How to sort the results in each section?
You could define number of sections and rows in it as following:
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// number of courses?
return 3;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return ((section == 0) ? 1 : 3);
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// return appropriate cell(s) based on section
if(indexPath.section == 0)
{
// Return 1 cell
}
else if(indexPath.section == 1)
{
switch(indexPath.row) {
case 0: // Initialize cell 1
break;
case 1: // Initialize cell 2
break;
...
}
}
return cell;
}
Here are the good tutorials to learn more:
http://www.appcoda.com/ios-programming-index-list-uitableview/
http://briterideas.blogspot.com/2012/07/uitableview-how-to-part-3-multiple.html
https://owenandrewsblog.wordpress.com/2012/01/29/uitableview-sections-tutorial/
So mi requirement is i have dataset like this
car - toyota
car
white
car - BMW
car
blue
car - Jaguar
car
brown
Bike - KTM
Bike
orange
Bike - Honda
Bike
black
like this i have n number of objects.
i need to generate o/p as following.
section names
car,bike...
inside car section i need toyota, BMW,Jaguar
inside Bike section i need KTM,Hond.
how can i achieve this
Note: I need to create sections and datas dynamically based on the data set
If any one know the solution kindly help me thanks in advance
the codes that i have used
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return sectionData.count;
//section data has only sections e.g. car,bike.
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 5;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [sectionData objectAtIndex:section];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
NSManagedObject *carobj = [StoredDataForDisplay objectAtIndex:indexPath.row];
if ([[carobj valueForKey:#"type"] isEqualToString:[sectionData objectAtIndex:indexPath.section]] ) {
cell.textLabel.text = [carobj valueForKey:#"name"];
}
return cell;
}
You just need to update the tableview datasource before showing these data. For example, you can create a NSDictionary with group names("car", "bike" etc) as the key, a NSArray as the value, so the value for key "car" will be an array of "toyota", "BMW", "Jaguar" objects.
You can then create a NSArray to hold all the group names in the order you need. groupArray = dataDictionary.allKeys;
Then you can display all group names and all items under this group:
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return groupArray.count;
//section data has only sections e.g. car,bike.
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[dataDictionary objectForKey:groupArray[section]] count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [groupArray objectAtIndex:section];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
NSManagedObject *carobj = [[dataDictionary objectForKey:groupArray[indexPath.section]] objectAtIndex:indexPath.row];
cell.textLabel.text = [carobj valueForKey:#"name"];
return cell;
}
You need call reloadData in table view when you change your data set. Your dataSourceDelegate look good, but in method numberOfRowsInSection need return valid rows number, rows number need get from your data set. And you can use for data storing nsdictionary + nsarray for fast access to data.
I'm trying to populate a grouped UITableView using an NSMutableArray. I want each element in the array to have its own section. i.e : One element (one row) per one section.
This is my code I have written so far.
#import "MailViewController.h"
#interface MailViewController ()
#end
#implementation MailViewController
NSMutableArray *mailboxes;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
mailboxes = [[NSMutableArray alloc] initWithObjects:#"Inbox", #"Drafts", #"Sent Items", nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return mailboxes.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [mailboxes objectAtIndex:indexPath.row];
return cell;
}
#end
Currently this is how it looks.
How can I get this the way I described above? (first section: Inbox, second section: Drafts, Third section: Sent Items etc.) I've gotten close but not quite there yet.
Thank you.
You should change:
cell.textLabel.text = [mailboxes objectAtIndex:indexPath.row];
to
cell.textLabel.text = [mailboxes objectAtIndex:indexPath.section];
These lines should go in the cellForRowAtIndexPath: method.
Your array index should be based on the sections and not the rows. Row is always fixed at zero.
Replace
cell.textLabel.text = [mailboxes objectAtIndex:indexPath.row];
With
cell.textLabel.text = [mailboxes objectAtIndex:indexPath.section];
If you want section headings as well implement the - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section and return a string based on the section..
With the code from other answers, you will be able to display one cell inside each section. What I prefer to do is have a multi-dimensional NSArray of pre-built cells and when I need them they're in index [section][row].
You currently have one array with just sections and trying to access them as rows (as other answers suggest). Your code won't work if you have more mailboxes in one table group..
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [mailboxes count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section
{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
switch(indexpath.section){
case 0:
cell.textLabel.text = [mailboxes objectAtIndex:indexPath.section];
case 1:
cell.textLabel.text = [mailboxes objectAtIndex:indexPath.section];
case 2:
cell.textLabel.text = [mailboxes objectAtIndex:indexPath.section];
default:
break;
}
return cell;
}
I am trying to create a table with dynamic data and I'm kind of stuck. Here is how my data is structured :
NSMutableArray *bigArray;
bigArray has many NSDictionary items.
each items has only one entry.
sectionName is the key, NSMutableArray is the value.
There are many objects in the value NSMutableArray.
I tried to explain this as simple as I could, here is the part where I'm stuck.
//easy
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [bigArray count];
}
//medium
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [[[[bigArray objectAtIndex:section] allValues] objectAtIndex:0] count];
}
I can't figure out this part how to implement this method based on my current data structure :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:#"MyCell"];
MyObject *obj = //Need this part
cell.textLabel.text = obj.name;
return cell;
}
Simply put, I'm trying to insert dynamic sections with dynamic data. I'm looking for advice from more experienced developers, how would you tackle this?
Assuming I understood well how your data is structured, here's how I would do it:
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MyCell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"MyCell"];
}
//this will get you the dictionary for the section being filled
NSDictionary *item = [bigArray objectAtIndex:indexPath.section];
// then the array of object for the section
NSMutableArray *mutableArray = [item objectForKey:#"sectionName"];
//you then take the object for the row
MyObject *obj = [mutableArray objectAtIndex:indexPath.row];
cell.textLabel.text = obj.name;
return cell;
}
Don't forget to set the reuse identifier for the cell prototype in the attributes inspector