deleteRowsAtIndexPaths doesn't release the cell? - iphone

I have a functionality in my table view i.e. when you tap in on cell it loads more cells in below the tapped cell and when you tap again on same cell those added cells gets deleted.
But I have got a strange behavior that when i call below method to delete added cells from table view, the dealloc method of cell isn't being called..(I have placed a NSLog in dealloc method)
[tableView deleteRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationTop]
and when I call insertRowsAtIndexPaths then new instance of cells are being created, in the instruments I checked that the previous instances remain in memory and new instances are being created again and again.
so please tell me that why is deleteRowsAtIndexPaths not calling release for deleted cell? and some solution for this problem. I am worried because application's real and virtual both memory consumption is keep increasing on continuous taps...

Do you use UITableView's dequeuereusablecellwithidentifier: method in cellForRowAtIndexPath: in order to create new cells?
If not, this is normal. UITableViews keep cells in memory in order to reuse them and avoid having to alloc/dealloc all the time.
You should take a look at this tutorial for example: http://www.mobisoftinfotech.com/blog/iphone/introduction-to-table-view/

Related

iPad UITableView flickering issue

I have a UITableView that contain about 20 rows in the iPad's viewport. I have a interval timer that will call UITableView's reloadData regularly(post it to UI thread).
Now when I scroll through the UITableView with medium speed (not so fast), that UITableView will refresh with flickering effect.
I have to write a function to manually update the UITableViewCell label by looping through all the items in the array (this array keep all the items that show on UITableView). I will execute this function when timer is running instead of calling reloadData (as I mentioned above). Then the flickering issue is gone.
I believe that reloadData should be better than looping through all the data because reloadData will only refresh the current showing Cells instead of all the rows, but I couldn't figure out why the flickering happens. Anyone know why?
One thing I have to mention is I did use the CellIdentifier correctly to reuse the cell and only create the cell when the retrieved cell is null.
Moreover, I do not have this issue in iPhone and I believe that it is because iPhone has lesser row compare to iPad.
Anyone can give some explanation about this issue?
I had the same problem with flickering when using reloadData. I solved it by using indexPathsForVisibleRows and cellForRowAtIndexPath: to only update the visible cells. Performance is good since I don't have to iterate over the whole data set, but only a limited number of visible cells.
reloadData causes the tableview to recreate the visible cells on screen which can result in a flickering since the cells get destroyed. There are better ways to reload the tableview. Are you using Core Data? If so the NSFetchedResultsController and it's delegate are a great way to update a tableview since it listens to changes in the underlying datasource and only updates the appropriate cells.

UITableView's cells release when not visible

I have a UITableView. each row is heavy object with videos, images etc.
When user scrolls this view how can I release the memory of not visible rows and load the current visible rows?
I assume you're talking about releasing memory that's used by the images and videos of your row, and not the row itself.
In your tableview delegate,
-(void) scrollViewDidEndDecelerating:(UIScrollView *)scrollView
tells you when the tableview scrolling has stopped.
[myTableView indexPathsForVisibleRows]
gives you an array of what is visible.
If your row is not in this array, it is not visible, and you can do your image/video cleanup on it.
Are you recycling UITableViewCells as per Apple's recommendations? If not, you MUST read Apple's docs. Inside the cellForRowAtIndexPath: delegate you should have something [customCell setMediaObjects:]. Inside your customCell class you can release all the previous mediaObjects from memory.
As others have said, you should make sure you are recycling cells properly, and not destroying things you would need to recreate anyway when the cell is reused.
But, you may want to release other assets that the cell or its views are retaining. Or if that cell has any pending download requests, for example, you may want to reset their priority or even cancel them when the cell is offscreen.
I think the cleanest way to do this is to just override -[UITableViewCell prepareForReuse]
This is called when the cell is put back into the reuse queue. If the user is moving up and down the table quickly, you may not want to clean the cell up the moment the cell is off the screen (by looking at indexPathsForVisibleRows, for example).
But when the cell is actually put back in the reuse queue, that is a good time to do that work since you know that cell won't appear again on screen until you dequeue and configure it again.
A Closer Look at Table-View Cells - Apple Documentation
When you call dequeueReusableCellWithIdentifier first 10 (just ten cells can be shown at screen at one moment) cells will be created, then they will be just loaded and configured for showing.
So, cells are not released.

how to dispose cells in UITableView when they are not needed?

I am creating a very long table with images and some text data. I am using resuable cells.
I am getting high memory allocations as I scroll the table down, may be due to new images loads and add to resuable cells.
I want to know is there a way to dispose the resuable cells when they are not in the view.
Please help!
You have no way to remove the reusable cells as this task is efficiently managed by the table view itself. According to me, but I need to see some code snippet to confirm, you're not disposing the images properly.
A typical case is when you load images using the -(UIImage *)imageNamed: method and in such case all images are stored in a OS managed cache which is not as efficient as manual alloc/release.
Another case is when you create the cell and forget to autorelease it. This means that in the tableView:cellForRowAtIndexPath: method when you instantiate the new UITableViewCell you must autorelease it before leaving the method (it will be retained by UITableView internal queue).

Regularly update UITableView

I have a UITableView which I need to update about 2-3 times a second via NSTimer. The cells in this table have UIButtons which respond to touchupinside. The problem is that this created extreme sensitivity. I could not press the button for too long otherwise it wouldn't register.
That issue was solved in
UIButton oversensitive
How can I solve the problem of regularly updating the table, while at the same time keeping the buttons responding naturally?
Update only the visible UITableViewCells instead of calling reloadData on the table. reloadData recreates the table cells each time it is called resulting in your touch events getting "lost" because they would go to the old deallocated table cells.
Instead of reloading the contents in tableview, try to reload them in a table cell. Subclass the cell and reload the necessary data in a cell. By doing like this, your button will not be created again and again. Only the data will be refreshed.

IPhone custom UITableViewCell Reloading

currently I'm struggling with this problem:
I got a UITableViewController that displays a tableView with different custom cells.
One custom cell displays a number (by a label). If you click on this cell, the navigationController moves to a UIPicker where the user can select the number to be displayes.
If the user moves back, the cell should display the updated value.
Problem:
I managed to reload the cells by calling
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.tableView reloadData];
}
in the UITableViewController.
This works only, if I don't use dequeueReusableCellWithIdentifier for the cell (tables won't show updates otherwise).
But in this case, memory usage grows and grows...
In addition, the program crashes after about 15 movements to pickerView and back - I think because the cell that should be reloaded is already released.
How can I update a reusable custom cell every time the view appears ?
What is the best solution ?
I think retaining cells should not be used ?
A general approach is to avoid reloading the whole table if only one cell is changed.
In such case, just get the reference to the UITableViewCell you want to "refresh" and invoke a [self setNeedsDisplay] from the main thread on it to trigger its refresh (will call the drawRect on it to trigger its drawing).
Have you set the appropriate id in the NIB? It has to be the same as you use when calling dequeueReusableCellWithIdentifier:
See step 3 here