Xcode remove cell with animation programmatically - ios

Hi i have been searching around to find a way to remove a static cell with animation but i have not found a solution to the problem.
I have also tried: [tableView deleteRowsAtIndexPaths:[self.taskArray objectAtIndex:indexPath.row] withRowAnimation:UITableViewRowAnimationFade];
but no success.

You need to hide cell before it is shown, in UITableViewDelegate's tableView:willDisplayCell:forRowAtIndexPath: method. This is the last method in your control where you can manipulate the cell display. It does not remove the space the cell takes, so another thing you can try is to set cell row's height to 0 using the tableView:heightForRowAtIndexPath: method of the same protocol.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
if (yourCell) {
return 0;
} else {
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
}

As your tableview is static, you cannot use deleteRowsAtIndexPath. The best option would probably be to migrate your data into a dataSource method for the tableview.
If this is impossible, then this answer ("UITableView set to static cells. Is it possible to hide some of the cells programmatically?") gives that the best method is to use the third party library
StaticDataTableViewController 2.0 (https://github.com/xelvenone/StaticDataTableViewController).
Otherwise you have to use the somewhat hacky method of changing the row height to 0.

Related

Get UITableViewCell from indexPath not Working

i was trying to updated the cell item while updating the height of the cell but its not working.
[_tblBillHistory beginUpdates];
[_tblBillHistory endUpdates];
these method i have used to updated the cell height
Err- > EXC_BAD_ACCESS(code=2,address=0x7fff5b4daf98)
this error message getting for cellForRowAtIndexPath method. Nslog also printing the selected row correctly. any idea??? thank you.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if((selectedPath!=nil ) & ([indexPath isEqual:selectedPath])) {
NSLog(#"%ld",indexPath.row);
UITableViewCell *tempCell = [_tblBillHistory cellForRowAtIndexPath:indexPath];
UIStackView *stkItems=(UIStackView *)[tempCell viewWithTag:8];
for(int i=0;i<20;i++)
{
UIButton *btn=[UIButton buttonWithType:UIButtonTypeSystem];
[btn setTitle:#"test button" forState:UIControlStateNormal];
[stkItems addArrangedSubview:btn];
}
return 700;
}
return 250;
}
I think this method is not good place to update cell's components.
If you want to add element to the cell you can create it at any other methods, for example:
- tableView:willDisplayCell:forRowAtIndexPath:
heightForRowAtIndexPath may be called many times (every reloadData or animation block).
You should divide your code, in heightForRowAtIndexPath you should only calculate height without request the cell (because the tableView not have cells in this method).
Adding or removing elements to the cell you can create in the didSelectMethod (but more better solution move this code to the cell or create a custom class for selected cell):
- tableView:didSelectRowAtIndexPath:
Please refer this
EXC_BAD_ACCESS in heightForRowAtIndexPath iOS
Try to replace following line
UITableViewCell *tempCell = [_tblBillHistory cellForRowAtIndexPath:indexPath];
with this one
UITableViewCell *tempCell = [self tableView:_tblBillHistory cellForRowAtIndexPath:indexPath];
This will stop recursive call as this is calling cellForRowAtIndexPath as a function not as data source of table view....

UItableviewcell Reuse issue in ios

Hello guys i think almost everyone who is in ios development may come across the issue of reuse of the UITableCell by using following code line.
RZRestaurantListingCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
I have search lot about this but not getting any desire answer so please help me out in this case.
I have the same issue as most of iPhone developer having after reusing the cell.
I have the UIProgressView inside my cell and one button is there for downloading the video and i am showing the progress there in progress view how much is left.
So Now what i have problem is when i have more data and going out of the screen at that time i am press the download button on very first row of the UITableviewCell then i am scrolling down so the progress also shown in bottom random one cell so the UI changes in two cell rather then one.
You need to implement -prepareForReuse method in your custom cell class and set all cell properties to default value.
- (void)prepareForReuse
If a UITableViewCell object is reusable—that is, it has a reuse
identifier—this method is invoked just before the object is returned
from the UITableView method dequeueReusableCellWithIdentifier:. For
performance reasons, you should only reset attributes of the cell that
are not related to content, for example, alpha, editing, and selection
state. The table view's delegate in tableView:cellForRowAtIndexPath:
should always reset all content when reusing a cell. If the cell
object does not have an associated reuse identifier, this method is
not called. If you override this method, you must be sure to invoke
the superclass implementation.
Refer here for more, https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableViewCell_Class/#//apple_ref/occ/instm/UITableViewCell/prepareForReuse
You need to assign a progress value inside the - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
RZRestaurantListingCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// If the cell is reused, the `-prepareForReuse:` of `UITableViewCell` will be called.
//!! Assign current progress value to this cell, otherwise, the progressBar.value may look like a random value.
//!! Because the current cell is reused from a disappeared cell.
cell.progressBar.value = ... ;
return cell;
}
The design may be complex, because the progress may be updated continuously when the cell is on the screen.
Use prepareforreuse method to clear content of cell before using it... e.g.
-(void)prepareForReuse
{
[super prepareForReuse];
self.textLabel.text = #"";
self.detailTextLabel.text = #"";
self.imageView.image = nil;
}

Access custom cell properties in heightForRowAtIndexPath

I have a custom UITableViewCell. I want to access the cells properties i.e. a UILabel etc. I tried inserting the following code:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CategorieCell *customCell = (CategorieCell *)[tableView cellForRowAtIndexPath:indexPath];
return ...
}
When I run the app, it crashed without giving me error details. The problem is with the new customCell I'm creating. Is there another way I can access the customCell.m objects?
About the crash, please note that you are using cellForRowAtIndexPath: wich is a method from the UITableViewDatasource that you have to implement, this method calls heightForRowAtIndexPath by default, so it will become a recursive
I assume that you want your custom cell in this method in order to get the height from it.
The best way to achieve this is write a class method on CategorieCell that gives you the height for a cell with certain data.
Other option is extract a method with the code to get the uitableviewcell for example
(CategorieCell*) categorieCellForIndex:(NSIndex)index selected:(BOOL)selected{
...
}
In heightForRowAtIndexPath should never be called cellForRowAtIndexPath.
The first one is called before the second one, and if you need to access to a label (for example to calculate the height of the text) you can normally init a cell.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
static CategorieCell *cell;
if (!cell) {
cell = [tableView dequeueReusableCellWithIdentifier:#"CellIdentifier"];
cell.frame = CGRectMake(0, 0, tableView.frame.size.width-tableView.contentInset.left-tableView.contentInset.right, cell.frame.size.height);
[cell layoutIfNeeded];
}
cell.label.text = myDatasourceText;
CGFloat cellHeight = ....
return cellHeight;
}
NOTE 1:
I used dequeueReusableCellWithIdentifier supposing you are using Interface Builder, otherwise you need to use alloc] initWithStyle:...];
NOTE 2:
As you see I'm setting the frame of the cell. This is needed because otherwise your cell will be (320 x 44) as default. You instead could be in iPhone 6/6+ (i.e. screen width: 414) or in an iPad, and you could need to calculate an height of a label according with his width and his text, and for this reason you need to set the frame of the cell.
NOTE 3:
I'm assuming you have a set of equal cell structure, and for this reason I'm using a static cell, so it will be reused without allocate other useless cells.
Try to register your custom cell class like so:
[self.tableView registerClass:[CategorieCell class] forCellReuseIdentifier:NSStringFromClass([CategorieCell class]);
and then in -tableView:heightForRowAtIndexPath: do something like:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CategorieCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass([CategorieCell class)];
}

XCode iOS7 - Dynamic cell with UITextView like Reminder App

I need to create an application that have the same behavior as built-in Reminder App. There are some problems to create this:
Cells that have dynamic height and "grow" as the content of the UITextView
Select the touched cell
Refresh the height of the cell when the user has edited the content(on the fly)
I've already solved the dynamic height, using some trick.
The problem that remains is:
How to know which cell the user has selected if the cell is "fully" with the UITextView ?
Right Now i've used the method textViewDidBeginEditing to know the cell and scroll the UITableView to it:
- (void)textViewDidBeginEditing:(UITextView*)textView
{
MemoViewCell* cell = (MemoViewCell *)[self parentCellFor:textView];
if (cell)
{
NSIndexPath* indexPath = [self.tableView indexPathForCell:cell];
currentIndexPath = indexPath;
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
}
}
- (UITableViewCell*)parentCellFor:(UIView*)view
{
if (!view)
return nil;
if ([view isMemberOfClass:[MemoViewCell class]])
return (UITableViewCell*)view;
return [self parentCellFor:view.superview];
}
How to refresh the cell height without lost the focus?
To this, i've used this method:
-(void)textViewDidChange:(UITextView *)textView
{
NSMutableDictionary *dataSourceItem = [self.model.dataSource objectAtIndex:currentIndexPath.row];
[dataSourceItem setObject:textView.text forKeyedSubscript:#"body"];
[self.model.dataSource setObject:dataSourceItem atIndexedSubscript:currentIndexPath.row];
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
When the text change, i get the new text, i change it in the Model and i call beginUpdated and endUpdates.
Sure, this works, but all is extremly slow... do you have some idea to to this in a more elegant way and maybe... efficient?
If i call reloadRowsAtIndexPaths: i lost the focus on the cell.
First of all, if you use the delegate method - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath; in your dynamic height trick, remember to implement this method along - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath;, it helps a lot in terms of performance.
Then to focus on your specific project, if I correctly understood your goal, what you really want is to update the layout of your table view only when your text view is modified. Currently you're updating it at each text change. You might consider using a condition inside -(void)textViewDidChange:(UITextView *)textView, such as :
if ([textView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height !=
textView.frame.size.height) {
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
The condition given as example will work only if your existing cell layout respects the intrinsic content size of the text view, otherwise you will need to adapt the condition.

Static UITableView with custom row heights

I'm trying to create detail view controller as a list of information and I think it would be nice and clean to present this with a static UITableView. But after that it came to my mind that on some level it might be difficult, so please resolve my doubts!
Every UITableViewCell has different style (some are custom, some are basic and few are right-detailed etc.).
What is more, content size of each cell may vary as I have long names put inside labels so they use autolayout to fit.
There is no problem when I have the same cells repeating but with different tex inside UILabels. In that case I use a simple:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (!self.prototypeCell) {
self.prototypeCell = [self.tableView dequeueReusableCellWithIdentifier:#"ActivityCell"];
}
[self fetchedResultsController:[self fetchedResultsController] configureCell:self.prototypeCell atIndexPath:indexPath];
CGSize size = [self.prototypeCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
return size.height;
}
I don't know how to deal with heightForRowAtIndexPath. I can give an identifier to each cell, call cellForRowAtIndexPath:, and make a big switch or if statement, but is it right? The same problem occurs while I think of cellForRowAtIndexPath: and populating those UITableViewCells. With those testing statements this code won't be pretty and readable.
Any ideas on that case?
In the delegate function of the table view named heightForRowAtIndexPath try to calculate the height for each row and then return it.
//return height for row
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(tableView==tblLanguage)
{
//Here calculate the dynamic height according to songs count for specific language
return (([[arrSongListForSpecificLanguage objectAtIndex:indexPath.row] count]*40)+40);
}
return 40.0;
}

Resources