I have two tableviews and cells are configured depending on which table view it is, they are implemented in the cellForRowAtIndexPath method via indexpath.section. However, the two tableviews have a different number of sections. Is there a way to go about this issue? Thanks
When i said they had different section numbers i meant the following:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if(tableView==byTeam) {
return [teamnameswithoutRepeat count];
} else {
return [JSONPointsArray count];
}
// Return the number of sections.
}
When i use the following in cellforrowatindexpath:
label.text=[currentarray objectAtIndex: indexpath.section];
there is a range error because indexpath.section is too big, it is using the JSONPointsArray to determine the number of sections, however when i run the app the by team tableview has the correct amount of sections.
Your cellForRow... method needs to be similar:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == byTeam) {
// process the "byTeam" table using the teamnamesiwthoutRepeat array
} else {
// process the other table using the JSONPointsArray array
}
}
Related
I'm trying to make a UITableView present a determined number of rows for a section, but even when I verify that its data source is returning x number of rows for numberOfRowsInSection, the table view shows x-1.
The exception to this unexpected behavior is if the numberOfRowsInSection is less than 3.
I've even put a breakpoint in cellForRowAtIndexPath and I confirmed it's being called for the row that is not appearing.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == SectionNumber_One) {
return 6;
} else {
return self.numberOfProjectRows; // This returns x, but x-1 rows are being shown
}
}
For example, if self.numberOfProjectRows is 5, only 4 rows are shown for the second section.
If I increase it manually to 6, it shows 5 rows but the data that should be in the 5th position, isn't there.
It doesn't seem to be related to screen size as I tested it on an iPad with same results.
Why is this happening? Is there some other possible modifier of the number of rows in a section?
I'm attaching an screenshot if it's of any help.
EDIT - Here are my delegate methods:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Cell with reuse identifier setup
if (section == SectionNumber_One) {
// cell setup for section one that's showing up ok
} else if (section == SectionNumber_Two) {
UITextField *projectField = cell.projectTextField;
if ([self.userProjectKeys count] > row) {
projectField.text = self.availableProjects[self.userProjectKeys[row]];
}
}
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Hide the password row for existing users
if (indexPath.row == FieldTag_Password && ![self.user.key vol_isStringEmpty]) {
return 0.0f;
} else {
return UITableViewAutomaticDimension;
}
}
The problem is probably not in your Datasource methods, but your Delegate methods, tableView(_:heightForRowAt:).
If you do not return a correct height for the cell, it won't show up.
It doesn't matter if you write 1000 cells in your datasource. If you don't return the height, they wont show up.
You are not comforming to the MVC pattern in implementing the table. You must return the count of the tableView's datasource, not variables of it.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == SectionNumber_One) {
return 6;
} else {
return [_displayingArray count]; // <-- here
}
}
If you want different items for each sections, then declare different datasource (ie array) for each of them.
EDIT: Even returning constant 6 is dangerous in the other section - you ought to add items to another fixed array and return that array's count in this delegate.
I have a tableViewController, and under that i want one static cell and rest of all will be dynamic cells . I have already run for dynamic cells , but within same tableViewController i also need to add one static cell, how can i achieve it?
Please Help
Thanks in advance.
you could do something like the following:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.dynamicContent.count + 1; // +1 for the static cell at the beginning
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0) {
// static cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"StaticCellIdentifier" forIndexPath:indexPath];
// customization
return cell;
}
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"DynamicCellIdentifier" forIndexPath:indexPath];
id contentObject = self.dynamicContent[indexPath.row];
// customization
return cell;
}
You cannot create static and dynamic cell at same time in a UITableViewController.
But you can hard code your static cell's data and load the data each time you reload your tableview.
You can keep all your cells in one section and keep checking for index path.row == 0 or create separate sections for them.
typedef NS_ENUM(NSUInteger, TableViewSectionType) {
TableViewSectionType_Static,
TableViewSectionType_Dynamic
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 2; // One for static cell, and another for dynamic cells
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
switch(section) {
case TableViewSectionType_Static:
return 1; // Always return '1' to show the static cell at all times.
case TableViewSectionType_Dynamic:
return [myDynamicData count];
}
}
With this approach your cells will be split into two sections and it will be easier to manage. And it will always show one cell, as number of rows returned for TableViewSectionType_Static is 1 always. It will show the dynamic cells based on your data count.
I am working on an app where I need to reorder rows of section 1. I could achieve the reorder by implementing the tableView delegates. When the table is in editing mode I show reorder for section 1 and no controls for rest sections, but the rows of rest section should be deleted by swipe to left.
I am not sure whether this is possible but my requirement is exact the same.
Work done by me:
Below are the delegates of tableView I implemented:
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
if ([self.myTable isEditing]) {
return UITableViewCellAccessoryNone;
}
return UITableViewCellEditingStyleDelete;
}
-(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 1) {
return YES;
}
return NO;
}
-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
The above code made the edit mode look as I wanted. Re-order sign got visible for only section 1 & red delete button is also not visible for rest sections (as desired).
Problem:
The rows of sections apart from section 1 were also not being deleted.When I swipe to left nothing happens.
In short in edit mode, section 1 should be re-order enabled and rest sections should work as they work in normal mode i.e swipe left to delete row should be functioning in tableview edit mode.
AFAIK you cannot achieve what you are trying. The two sections are part of the same table which is being edited. So once the table is in editing mode, it will affect all the sections and rows.
what you can do is divide the data in the two sections into two separate tables and load the tables in the header view of each section like this
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 2;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 0;
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
if (section == 0) {
TableViewController1 *tab1 = [[TableViewController1 alloc] initWithStyle:UITableViewStylePlain];
return tab1.tableView;
} else{
TableViewController2 *tab2 = [[TableViewController2 alloc] initWithStyle:UITableViewStylePlain];
return tab2.tableView;
}
}
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return self.parentTable.frame.size.height/2;
}
tab1 will have data from first section and similar case for tab2 (forgive the variable naming). The parent table should have grouped style and also scrolling should be disabled for it. This way the two sections can be edited independent of each other. Also, this categorises data and each section becomes independently scrollable. Hope this helps and answers what ur looking for.
I am new to ios programming so bear with me if the question is simple. I have a core data table mapped to a table view controller. The data in it currently looks as follows - there is one prototype cell:
I need to sum up the data by dates and show the details of each date in a different section with the summed up total coming up as the first row. Something like:
My question is is this doable? I am thinking I need to create sections and two prototype cells within each table cell. Would appreciate quick feedback.
Thanks all!
The easy way to do this is using section headers. You can either use a single string (#"%#: %#", date, total) or a wrapper view with a label on the left for the date and on the right for the total.
-(NSString *) tableView:(UITableView *)tv titleForHeaderInSection:(NSInteger)s
{
NSString *dateString = [self dateStringForSection:s];
float total = [self totalForSection:s];
return [NSString stringWithFormat:#"%#: %0.2f", dateString, total];
}
Or
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
return [self wrappedHeaderForSection:s];
}
You'll have to implement dateStringForSection: or wrappedHeaderForSection: appropriately, of course.
The easiest way is to style your UITableView to 'UITableViewStyleGrouped'.
UITableView *tab = [[UITableView alloc] initWithFrame:rect style:UITableViewStyleGrouped];
Or you can go to interface builder and in Table View change style from plain to grouped.
The style 'Grouped' divides your table into multiple sections.
The using UITableViewDelegate methods specify all the parameters.
// Tell the number of section in table
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return numberOfSections;
}
//Tell the number of rows in each section
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == 0)
{
return 2;
} else if(section == 1)...
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 0 && indexPath.row == 0)
{
//Show Amount for Jul 02, 2013
cell.textLabel.text = #"Jul 02, 2013";
cell.detailTextLabel = #"20.35";
}
// Do the same for all rows and section in table.
}
For further reference -
http://mobisoftinfotech.com/iphone-uitableview-tutorial-grouped-table/
You should also definitely check out the Sensible TableView framework. Saves me tons of time when working with Core Data.
I need to create a grouped uitableview that includes some sections and possibly different cell types in each sections.
I am trying to create something like old foursquare app, user page (includes 'leaderboard', 'friend suggestions', 'friends', 'stats', 'most explored categories' ... sections).
I am fairly new to ios programming, so that view may not be a grouped uitableview.
What I especially stuck is creating different cells for sections, and finding out which cells are clicked.
My data source will be 2 different NSArray* that consists of different data types, that's why I need different custom cells.
Since you have two different sets of data and you need to display both in different sections, you have to split the data source methods into two.
Basically, choose which dataset you want to be first and off you go.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(section)return secondArray.count;
//Essentially, if statements evaluate TRUE and move forward if the inside is 1 or greater (TRUE == 1)
return firstArray.count;
//If the first if statement return hits, then the code will never reach this statement which turns this into a lighter if else statement
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.section)
{
//do stuff with second array and choose cell type x
}
else
{
//do stuff with first array and choose cell type y
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//Get the cell with: UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if(indexPath.section)
{
//perform action for second dataset
}
else
{
//perform action for first dataset
}
}
For headers, you can use either of these methods and just keep the same type of styling as above:
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;
You can create multiple custom subclasses of UITableViewCell, and in the tableView:cellForRowAtIndexPath: method for your UITableViewDataSource, you can use if-statements to determine what type of cell to use.
For example, here's a rough outline of what I might do:
-(UITableViewCell *)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//First, determine what type of object we're showing
if (indexPath.section == 0) {
//Create and return this cell.
} else if (indexPath.section == 1) {
//Create and return this cell.
}...
}
Here's how you'd implement numberOfRowsInSection:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (section == 0) {
return [firstSectionArray count];
} else if (section == 1) {
return [secondSectionArray count];
} ...
}
For didSelectRowAtIndexPath
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0) {
ObjectSelected *objectSelected = [firstArray objectAtIndex:indexPath.row];
//Now you've got the object, so push a view controller:
DetailViewController *dvc = [[DetailViewController alloc] init];
dvc.objectSelected = objectSelected;
[self.navigationController pushViewController:dvc];
} else if (indexPath.section == 1) {
//Same thing, just call [secondArray objectAtIndex:indexPath.row] instead!
}
}