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/
Related
I have a table that stores some data. Let's say data is too big to load into memory all at once. I want to show this data in UItableView.
-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [Item MR_numberOfEntities];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// How to get object for this row ???
return cell;
}
The only way i knew is to load all data into array with
NSArray *items = [Item MR_findAll];
But i don't want to do that. User will be shown first 10 rows, and why should i load all them from CoreData. Is there any way to fetch them one by one using MagicalRecord?
According to docs you need to init fetch request and also you may want to set the fetch offset depending on scroll progress.. but you will have to trace it manually. Here is a basic approach how it can be achieved.
PS. I haven't tested this code . I just wrote it in the text editor :). but it should work as you requested. e.g loading items with limit 10.
#property (nonatomic) int itemCount;
#property (nonatomic, strong) NSMutableArray * items
static const int FETCH_LIMIT = 10;
-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _itemCount;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Classic start method
static NSString *cellIdentifier = #"MyCell";
MyCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell)
{
cell = [[MyCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MainMenuCellIdentifier];
}
MyData *data = [self.itemsArray objectAtIndex:indexPath.row];
// Do your cell customisation
// cell.titleLabel.text = data.title;
if (indexPath.row == _itemCount - 1)
{
[self loadMoreItems];
}
}
-(void)loadMoreItems{
int newOffset = _itemCount+FETCH_LIMIT; // Or _itemCount+FETCH_LIMIT+1 not tested yet
NSArray * newItems = [self requestWithOffset: newOffset];
if(!newItems || newItems.count == 0){
// Return nothing since All items have been fetched
return;
}
[ _items addObjectsFromArray:newItems ];
// Updating Item Count
_itemCount = _items.count;
// Updating TableView
[tableView reloadData];
}
-(void)viewDidLoad{
[super viewDidLoad];
_items = [self requestWithOffset: 0];
_itemCount = items.count;
}
-(NSArray*)requestWithOffset: (int)offset{
NSFetchRequest *itemRequest = [Item MR_requestAll];
[itemRequest setFetchLimit:FETCH_LIMIT]
[itemRequest setFetchOffset: offset]
NSArray *items = [Item MR_executeFetchRequest:itemRequest];
return items;
}
Hope you find it helpful :)
I have a button, a pickerview and a tableview. When I push the button, the current selection of pickerview will be filled in the table view. Here is the code of button which pick value from pickerview
- (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 *msgCourse=[[NSString alloc ]initWithFormat:#"%# ",course];
NSString *msgSeason=[[NSString alloc ]initWithFormat:#"%# ",season];
NSString *msgYear=[[NSString alloc ]initWithFormat:#"%# ",num];
}
Then I want to populate msgCourse,etc to my tableview
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
...Content from above msgCourse and etc
return cell;
}
How to fix the gap in my second part please? Or any example to look at please?
Check the following code to decide whether or not that fits into your requirements based on what I understand from your question. If it does not, please leave a comment then I will try my best to follow up.
First Step: if you have not done the delegation via storyboard, here is the first thing that you should do programatically:
-(void)ViewDidLoad
{
tableView.delegate = self;
tableView.datasource = self;
}
Second Step: I have not seen a mutablearray in your code, but I assume that you are going to make msgCourse to NSMutableArray.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// I assume you have only one section
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [self.msgCourse count];
}
- (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;
}
Last Step: By the way, do not forget to add the following line of code into your button action to reload your tableView, I assume you update the NSMutableArray and would like to refresh the tableView.
- (IBAction)addCourse:(UIButton *)sender {
.....
.....
.....
[tableView reloadData];
}
Here is the good tutorial, it is worth to duplicate for the sake of learning: http://www.appcoda.com/ios-programming-tutorial-create-a-simple-table-view-app/
i am a developing a ios app with a view controller and a table view in it. i am trying to load list of items in 3 groups but when i compile it it shows correct count but not showing all the items jus repeating items. please help. let me post my code here.
#interface ViewController ()
#end
#implementation ViewController {
NSArray *menuItems;
NSArray *menuItems2;
NSArray *dash;
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor colorWithWhite:0.6f alpha:1.0f];
self.tableView.backgroundColor = [UIColor colorWithWhite:0.6f alpha:1.0f];
self.tableView.separatorColor = [UIColor colorWithWhite:0.15f alpha:0.2f];
menuItems = #[#"itm1", #"itm2", #"itm3", #"itm4"];
menuItems2 = #[#"itm1", #"itm2", #"itm3", #"itm4"];
dash = #[#"itm1", #"itm2"];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 3;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
if (section == 0) {
return [menuItems count];
}
if (section == 1) {
return [menuItems2 count];
}
if (section == 2) {
return [dash count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = [menuItems objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
return cell;
}
#end
Your cellForRowAtIndexPath... method needs to be written so the cell is populated with proper data based on the cell's section and row. Right now you don't do anything but use an empty cell.
You don't configure your cells. After dequeuing a cell, you have to set its title.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = [menuItems objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Get the correct array, depending on the current section.
NSArray *items = nil;
if (indexPath.section == 0) {
items = menuItems;
}
else if (indexPath.section == 1) {
items = menuItems2;
}
else if (indexPath.section == 2) {
items = dash;
}
// Get the string from the array and set the cell's title
NSString *title = items[indexPath.row];
cell.textLabel.text = title;
return cell;
}
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 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 :)