I have a UIViewController with a UITableView in it. I have 3 sections for the UITableView, like this.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 3;
}
and my cells set up like this...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ContactInfoCellIdentifier";
NSUInteger section = [indexPath section];
UITableViewCell *cell;
switch (section)
{
case 0:
{
...
break;
}
case 1:
{
...
break;
}
case 2:
{
...
break;
}
default:
break;
}
return cell;
}
but for some reason case 2, section 3 never gets called. Any ideas why this might be?
You need to instantiate the UITableViewCell like this UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:"YourIdentifier"];
Related
Is it possible to get the section count for the respective selected row in a UITableView
yes you can check for section with
indexPath.section
If you have NSIndexPath you can get row by
indexPath.row
or section by
indexPath.section
Try the following sample code:
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 5;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSInteger rows = 0;
switch (section) {
case 0:
rows = 7;
break;
case 1:
rows = 21;
break;
case 2:
rows = 3;
break;
case 3:
rows = 1;
break;
case 4:
rows = 5;
break;
default:
break;
}
return rows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CELL" forIndexPath:indexPath];
// Configure the cell...
cell.textLabel.text = [NSString stringWithFormat:#"section : %ld & rows : %ld",(long)indexPath.section,(long)indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//This will print which row of which section is clicked
NSLog(#"section : %ld & rows : %ld",(long)indexPath.section,(long)indexPath.row);
}
which is right !
NSArray <NSIndexPath *>*rows = [tableView indexPathsForSelectedRows];
I solved what i was looking for. I wanted to get all the section number for the respective selected rows in it, on the button click.
I used
NSArray *paths = [self.tableView indexPathsForSelectedRows];
I have a custom cell with multiple cell Identifiers. I tried the following code:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 2;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellID;
switch ([indexPath section]) {
case 0:
cellID = #"firstCell";
break;
case 1:
cellID = #"secondCell";
break;
default:
break;
}
customCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID forIndexPath:indexPath];
return cell;
}
When I run the app, it displays the first cell 2 times, even though in the storyboard, there are 2 cells with different objects inside.
Is [indexPath section] really what you want?
I think you want [indexPath row]
I have managed to make the TableView expandable. The problem is that when I start the app, it's always opened. I want it to be closed, and to be opened just when I hit the row.
What am I missing here? How can I set it to be open at start?
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 3;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (!indexPath.row)
{
// first row
cell.textLabel.text = #"Expandable"; // only top row showing
}
else
{
cell.textLabel.text = #"Some Detail";
cell.accessoryView = nil;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canCollapseSection:(NSInteger)section
{
return YES;
}
You first create a regular table with some array of booleans that holds the state of each row (open/close).
Then, when you hit a first row in a section, I reload the table with new rows:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//subject hitted
if (indexPath.row == 0)
{
// set relevant boolean here ,also , reload the table again with the new rows
collapsedRows[indexPath.section]= ! collapsedRows[indexPath.section];
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section]withRowAnimation:UITableViewRowAnimationFade];
}
//sub subject hitted
else
{
}
}
I had a simple question regarding a table view with 3 different kinds of prototype cells. The first two occur just once while the third occurs 4 times. Now what I'm confused about is how to specify in my cellforRowatindexpath which cell prototype to use for which row. So, I want something like for row 0, use prototype 1, for row 1, use prototype 2, for rows 3,4,5 and 6 use prototype 3. What's the best way to do this? Do i give each prototype an identifier and then use dequeueReusableCellWithIdentifier:CellIdentifier ?
Can you'll provide some sample code?
EDIT:
Still not working. This is the code I have at the moment. ( I only have one case for the switch statment because I just want to test and see if the cell is being generated in the first row or not, but currently table view is blank)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
switch(indexPath.row)
{
case 0: {static NSString *CellIdentifier = #"ACell";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:#"ACell"];
if(cell==nil) {
cell=[[UITableViewCell alloc]
initWithStyle:(UITableViewCellStyleDefault) reuseIdentifier:#"ACell"];
}
return cell;
break;
}
}
}
Acell is my identifier for a cell prototype that I created. I
If you are using three prototype then use three identifiers. Because only one identifier will cause problem. And you will get wrong result. So code like this.
if(indexPath.row==0){
// Create first cell
}
if(indexPath.row==1){
// Create second cell
}
else{
// Create all others
}
You can use switch case also here for best performance.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (cell.tag == 0)
{
return array1.count;
}
else(cell.tag == 1)
{
return array2.count;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier;
NSString *membershipType = [membershipTypeArray objectAtIndex:indexPath.row];
if ([membershipType isEqualToString:#"silver"]||[membershipType isEqualToString:#"gold"])
{
cellIdentifier = #"cell";
}
else if ([membershipType isEqualToString:#"platinum"])
{
cellIdentifier = #"premiumCustomCell";
cell.customCellImageView.image = [cellImageArray objectAtIndex:indexPath.row];
}
cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[CustomCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.headingLabel.text = [titleArray objectAtIndex:indexPath.row];
}
Here i wrote code like:
#pragma mark == Tableview Datasource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSInteger nRows = 0;
switch (section) {
case 0:
nRows = shipData.count;
break;
case 1:
nRows = dataArray1.count;
break;
default:
break;
}
return nRows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *cellIdentifier = #"cellIdentifier1";
NSString *cellIdentifier1 = #"cellIdentifier2";
SingleShippingDetailsCell *cell;
switch (indexPath.section) {
case 0:
cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
//Load data in this prototype cell
break;
case 1:
cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier1];
//Load data in this prototype cell
break;
default:
break;
}
return cell;
}
This should be easy, but I'm having trouble.
I have a static UITableView with a cell that I would like to remove programmatically if it's not needed.
I have a IBOutlet for it
IBOutlet UITableViewCell * cell15;
And I can remove it by calling
cell15.hidden = true;
This hides it, but leaves a blank space where the cell used to be and I can't get rid of it.
Perhaps a hack would be to change the height of it to 0?
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:indexPath
{
//what would I put here?
}
Thanks so much!
You can't really deal with this in the datasource since with static tables you don't even implement the datasource methods. The height is the way to go.
Try this:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell == cell15 && cell15ShouldBeHidden) //BOOL saying cell should be hidden
return 0.0;
else
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
Update
It appears that, under autolayout, this may not be the best solution. There is an alternative answer here which may help.
You can use tableView:willDisplayCell and tableView:heightForRowAtIndexPath with the cell identifier to show/hide static tableview cells, but yo must implement heightForRowAtIndexPath referring to super, not to self. These two methods work fine for me:
(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([cell.reuseIdentifier.description isEqualToString:#"cellCelda1"]) {
[cell setHidden:YES];
}
}
and
(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
if ([cell.reuseIdentifier.description isEqualToString:#"cellCelda1"]) {
return 0;
}
return cell.frame.size.height;
}
Depending on how your table is supposed to work, in your data source you can implement tableView:numberOfRowsInSection: to return 0 rows for the section based on your necessary logic.
Updated for your comment:
The section parameter will be populated by iOS when your implementation is called so all you need is a switch to handle the section that has the row you ant removed/hidden. Example below:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
switch(section) {
case 0: // first section of your table, change for your situation
return 0;
default:
return 0;
}
}
It for only constant cell
-(void)tableViewSearchPeopleCellHide:(BOOL)hide{
searchCellShouldBeHidden=hide;
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]];
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
cell.hidden=hide;
self.searchPeople.hidden=hide;//UILabel
[self.tableView reloadData];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (searchCellShouldBeHidden) //BOOL saying cell should be hidden
return 0.0;
else
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
The first thing you can do is tag the cell from storyboard which you want to hide.
Put some standard number which you can identify.
Add this code.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
if (cell.tag==10) { //I have put 10 for some static cell.
cell.hidden=YES;
return 0;
}
cell.hidden = NO;
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
Set the cell you want to hide to hidden somewhere in your code. Add this code: (If your cell has different row height, then you need to override more functions)
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
int rowCount=0;
for ( int row=0; row<[super tableView:tableView numberOfRowsInSection:section]; ++row){
NSIndexPath* path=[NSIndexPath indexPathForRow:row inSection:section];
UITableViewCell* cell=[super tableView:tableView cellForRowAtIndexPath:path];
if (!cell.hidden){
++rowCount;
}
}
return rowCount;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
int realRow=-1;
for ( int row=0; row<[super tableView:tableView numberOfRowsInSection:indexPath.section]; ++row){
NSIndexPath* path=[NSIndexPath indexPathForRow:row inSection:indexPath.section];
UITableViewCell* cell=[super tableView:tableView cellForRowAtIndexPath:path];
if (!cell.hidden){
++realRow;
}
if (realRow==indexPath.row)
return cell;
}
return nil;
}
Use index path to identify the cell in tableview height delegate and return 0
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if someCondition {
if indexPath.row == 1 || indexPath.row == 2 || indexPath.row == 3 {
return 0
}
}else{
if indexPath.row == 4 {
return 0
}
}
return super.tableView(tableView, heightForRowAt: indexPath)
}