I have section:1 has 11 rows. I set height like this
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 0) return 350;
else if (indexPath.section == 1) {
return 150;
}
else return 0;
}
if I set cell.hidden = YES; how can I remove the cell because if cell.hidden = YES it will be show space but I don't want that space I want if the cell is hidden directly remove from the secrion:1
or if I can set height for every hidden cells for 0.0
Thanks
EDIT
there is no NSArray for tableView it is customized like this
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (section == 0) { return 1; }
else if (section == 1) {
int retype = [type intValue];
if (retype == 1 || retype == 5 || retype == 10) {
return 0;
}
else if (retype == 11) { return 9; }
else if (retype == 14) { return 4; }
else {
return 11;
}
}
else return 0;
}
and for the cell configure like this
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleGray;
}
int truef = [*nsstring* intValue];
if (indexPath.section == 1) {
if (indexPath.row == 0) {
if (truef == 0) {
cell.hidden = YES;
}
else {
cell.titleLabel.text = #"True";
}
}
}
EDIT 2
This the error after use deleteRowsAtIndexPaths
reason: 'Invalid update: invalid number of rows in section 1. The number of rows contained in an existing section after the update (11) must be equal to the number of rows contained in that section before the update (11), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out)
You don't need to hide cell. The appropriate way here is to remove this cell from your dataSource and remove it from table view via
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
EDIT
Well... you will agree with me that "magical numbers" which you are using is not good way.
I see the following solution here: you put all your numbers which you return in
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
into instance variables, like
#property (assign, nonatomic) numberOfRowsInSection0;
than you can decrease this variable and remove the LAST row. In you situation you will be able remove only last row from table view.
Conclusion: the solution above just a hack which will allow you to remove only last row in your table. You have to review you code again and change logic in order to use array or any other storage. The table view assumes that you have some data source, but you don't, that is the core of you problem.
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
if(cell.hidden) { return 0.0f; }
Related
I have a table with one custom cell with one label and one textfield.Am re-using the same cell with some 5 rows. I want to display one view beneath my textfield only if user enters on the textfield. When am entering data in first textfield view should be hidden for other rows and respectively for all other rows. Default height must be 120 and when am displaying my view row height should increased to 250. Here is my code,
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 120;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"DetailsTableCell";
cell = (NewsDetailsTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[NewsDetailsTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
if (indexPath.row == 0) {
cell.newView.tag = 200;
}
else if (indexPath.row == 1) {
cell.newView.tag = 201;
}
else {
cell.newView.tag = 202;
}
return cell;
}
Here new view is my UIView which am displaying on text change.
- (IBAction)textFieldChanged:(UITextField *)textField replacementString:(NSString *)string {
NSIndexPath *indexPath = [newsTable indexPathForCell:(NewsDetailsTableViewCell*)[[textField superview] superview]];
NSIndexPath *myPath = [NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section];
NewsDetailsTableViewCell *newsTableCell = (NewsDetailsTableViewCell*)[newsTable cellForRowAtIndexPath:myPath];
if (indexPath.row == 0 && newsTableCell.newView.tag == 100) {
newsTable.rowHeight = 250;
newsTableCell.newView.hidden = false;
} else if (indexPath.row == 1 && newsTableCell.newView.tag.tag == 101) {
newsTable.rowHeight = 250;
newsTableCell.newView.hidden = false;
} else {
newsTable.rowHeight = 250;
newsTableCell.newView.hidden = false;
}
}
Am getting my view in my text change but row height is not getting changed. Also It still showing 120 height.
Also I tried this,
NSArray* rowsTobeReloaded = [NSArray arrayWithObjects:indexPath, nil];
[newsTable reloadRowsAtIndexPaths:rowsTobeReloaded withRowAnimation:UITableViewRowAnimationNone];
But it didn't work. Should I re-load my tableview again in text change? or am I missing something?
You have to modify the logic in the below method:
The selectedRowNum can be modified as per the row in which the textField is to be shown.
Also, cellForRowAtIndexPath is not used for setting the height of rows in a tableview. Everytime, we call the reloadData or reloadIndexes the heightForRowAtIndexPath method is called.
YOu need to change height in
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (usingNewView){
return 250;
}
return 120;
}
And set logic for usingNewView in
- (IBAction)textFieldChanged:(UITextField *)textField replacementString:(NSString *)string
I have a very strange situation in my app and i can't explain or locate the bug.
I have a UIViewController with a tableView in it.
In the table view I have 3 prototype cells, also i have 2 section that are divided like so:
first section: row 0 (cell ID: episodeScrollersCell)
second section: row 0 (cell ID: addCommentsCell)
: row 1+ (cell ID: commentCell)
The required methods in the protocol are listed below.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger rowNum;
if(section == 0){
rowNum = 1;
}else{
rowNum = 1; // here is the problem. If i change the number of row to above 1
}
return rowNum;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier;
if(indexPath.section == 0){
cellIdentifier = episodeScrollersCell;
}else if (indexPath.section == 1 && indexPath.row == 0){
cellIdentifier = addCommentsCell;
}else{
cellIdentifier = commentCell;
}
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
return cell;
}
Now the problem arises when I want to have 2 rows or above in the second section (i.e to have 2 prototype cells in one section), the view Controller won't show. I've logged the cellForRowAtIndexPath: method to see if the cells gets loaded and they do.
Any advice?
Thanks,
What you seem to be doing is trying to dequeue a reusable cell with a chance that no cell has been created before. However, if no cells have been created/allocated, then the dequeue will return a nil value. This tells the program that for the given indexPath there is NO cell to be displayed.
So, if you get a nil value from the dequeue function, your table will try to create a new cell with the given cell identifier. So, I would suggest you do something like the following:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier;
if(indexPath.section == 0){
cellIdentifier = episodeScrollersCell;
}else if (indexPath.section == 1 && indexPath.row == 0){
cellIdentifier = addCommentsCell;
}else{
cellIdentifier = commentCell;
}
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(!cell){
if(indexPath.section == 0){
//Initialise a new cell here, through a NIB or code
//For eg. cell = [[UITableViewCell alloc] initWithStyle: ...];
}
//Do the specific initialisation for each type of cell you need here
}
return cell;
}
This way, when the dequeue function returns a NIL value, your program automatically creates a new cell to fit in that place.
Hope this helps.
I am using UITableView with group-type, and I am adding different content on UITableViewCell
and each indexPath.section I am checking in UITableViewCell delegate method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
cellIdentifier = (indexPath.row % 2 == 0 ? #"EvenCell" : #"OddCell");
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault
reuseIdentifier:cellIdentifier];
if (indexPath.section == 0)
{
// adding image
// called
}
else if (indexPath.section == 1)
{
// adding lable
called
}
else if (indexPath.section == 2)
{
// adding panorma gps
called
}
else if (indexPath.section == 3)
{
not called // this section problem
}
else if (indexPath.section == 4)
{
not called // this section problem
}
}
return cell;
}
I have given number of section 5, but it is calling only indexPath.section 0, 1, and 2 only.
The problem is that that you only have only two types of cellIdentifier values (i.e. two types of cells you're reusing), but you appear to have five different layouts. The problem is that layouts are only called if a reused cell was not found. Thus, by the time you get down to section 3, dequeueReusableCellWithIdentifier is probably succeeding and reusing a cell that has scrolled off screen, and thus your code inside the if (cell == nil) block is not getting called at all for sections 3 and 4.
You can remedy that by either having more cell types, unique to the section number, too, e.g.:
NSString *cellType = (indexPath.row % 2 == 0 ? #"EvenCell" : #"OddCell");
NSString *cellIdentifier = [NSString stringWithFormat:#"%#-%d", cellType, indexPath.section];
You haven't shared what the even/odd logic is used for, so I'm not entirely sure what that's needed for. Assuming it's for something simple like backgroundColor, then I might be inclined to drop even/odd from the cellIdentifier altogether (and move the setting the background color outside the if (cell==nil) block), and just use the section number for the cell identifier:
NSString *cellIdentifier = [NSString stringWithFormat:#"MyCellSection-%d", indexPath.section];
We'd need a better sense of how different the various cells are configured (what is the degree of commonality) to make concrete suggestions on the best way to format this. But the key issue is that your cellIdentifier choices have to correspond to what's inside the if (cell == nil) block.
make sure you are returning 5 from here
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 5;
}
You call a method to the number of sections as follows?
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 5;
}
Try call your methods after if(cell == nil):
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault
reuseIdentifier:cellIdentifier];
}
if (indexPath.section == 0) {
// adding image
// called
}
else if (indexPath.section == 1) {
// adding lable
called
}
else if (indexPath.section == 2) {
// adding panorma gps
called
}
else if (indexPath.section == 3) {
not called // this section problem
}
else if (indexPath.section == 4) {
not called // this section problem
}
Is it possible to delete rows from a UITableView at runtime when all of the sections and rows are defined statically in a nib?
In the following storyboard scene, can I delete the "Addr 2" field at runtime? In this case I have not provided a data source to the UITableView.
I don't know about "delete" but you can hide the row using tableView:heightForRowAtIndexPath:.
- (void)methodToToggleAddr2CellVisibility
{
self.addr2CellIsHidden = !self.addr2CellIsHidden;
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
- (float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 1 && indexPath.row == 1) { // the cell you want to hide
if (self.addr2CellIsHidden == YES) {
return 0;
} else {
return 44;
}
}
return 44;
}
I am trying to aggregate data from three social networks (Facebook,LinkedIn,Twitter). I have all the appropriate and correct feeds and I also have difference cell types for them.
The question i want to ask is, how can i make a UITableView, containing 10 sections with 3 cells(plus three different cell types) per section in this order
Section 1:
[Facebook cell index 0 of the feed array]
[Twitter cell index 0 of the feed array]
[LinkedIn cell index 0 of the feed array]
Section 2:
[Facebook cell index 1 of the feed array]
[Twitter cell index 1 of the feed array]
[LinkedIn cell index 1 of the feed array]
Section 3:
etc etc etc
Play with the table view's data source & delegate. What's important is to use 3 different cell identifiers for 3 types of cells (unless you want them to have same look).
-numberOfSectionsInTableView: {
return 10;
}
–tableView:numberOfRowsInSection: {
return 3;
}
-tableView:cellForRowAtIndexPath:(NSIndexPath*)indexPath {
if (indexPath.row == 0) {
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:#"FacebookCell"];
if (cell == nil) {
// Init FB cell here
}
// Load FB feed data into the cell here
return cell;
}
else if (indexPath.row == 1) {
// Twitter Cell, remember to user a different cell identifier
}
else ...
}
-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 3;
}
-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
return 10;
}
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString * cellIdentifier = #"cellId";
customCell * cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(indexPath.row == 0)
{
cell.textLabel.text = [FbFeed objectAtIndex:indexpath.section];
// set FacebookCell
cell
}
else if (indexPath.row == 1)
{
// set TwitterCell
cell.textLabel.text = [tweetFeed objectAtIndex:indexpath.section];
}
else if (indexPath.row ==2)
{
cell.textLabel.text = [linkedinFeed objectAtIndex:indexpath.section];
//set linkedin
}
return cell;
}
To build off the example, this can be used for any multiple type cells. You don't always have to use the row number to decide the type. You can get an object at the row and decide what type to show.
Also, if you are using storyboard, just add another prototype cell in the table, assign it a unique identifier, and set it up so you can use it. Works really well if you need different layouts that depend on the data returned.
-tableView:cellForRowAtIndexPath:(NSIndexPath*)indexPath {
//Check what cell type it is. In this example, its using the row as the factor. You could easily get the object and decide from an object what type to use.
if (indexPath.row == 0) {
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:#"Type1Cell"];
return cell;
}
else if (indexPath.row == 1) {
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:#"Type2Cell"];
return cell;
}
else {
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:#"Type3Cell"];
return cell;
}
}