UITableView :cellForRowAtIndexPath Continues being called - objective-c

I have a UITableView Controller and a UITableView. I have everything set up using the delegates etc, and it populates fine. I notice a small bug however with the following method:
:cellForRowAtIndexPath
I am noticing that this method is continually called every time I scroll the table. Even after the table is populated, it continues to call. Basically, a cell moves out of view, when it comes back in view, it is calling it again. I had NSLog print out the cell contents within that method, which is how I know it continues to call.
Should that function not just call once per cell, to populate it, then be done?

Nope. That's called every time a cell is needed, and a cell is needed every time one is rendered.
UITableView is a very clever little critter. It literally keeps only the cells it's displaying, plus a cache of literally two or three more. When the time comes to scroll a cell on that wasn't on, it can be asked for a cell from the cache, and if there is one, it gets reused.
This way HUGE data sets can be displayed in a UITableView, because there really aren't a large number of cells in memory, only the ones on the screen and a small cache.

This is correct behavior. It has to do with the dequeueing of UITableViewCells. That is why cell reuse is important. This way there are ideally a finite, small amount built in memory that continually get reused.
Check out the docs for more info and code samples.

Related

VoiceOver reading twice each element - Inconsistent Behavior

I am working on Accessibility. I am using XIB file and I enabled all the views which need to be read by voiceover.Now the issue is first cell in tableview is reading twice by the voiceover. That happens only first time. I have multiple cells in tableview. But Voiceover reading first cell that too first time. If I swipe to next cells and come to the first cell again it reads only once.
Its very Inconsistent behavior. I could not able to find out the problem. I tried by passing nil values to both accessibilityLabel and accessibilityValue of the cells. But no impact on the Issue.When I disable the accessibility from the XIB file and enable it by programmatically also, but no Use.
Any Suggestions on this would be helpful.
You positing the UIAccessbilitypostnotification for the table with (Screenchange notification), will leads to read twice.
Dont post screenchange notification for Table view. UIKit will handle that by default.

Blinking image in table cell

I want to have a blinking image (swaps between two images) in table cells.
What seemed most natural to me is as follows:
Set a NSTimer to goes every .5 seconds, calling -blink:
In -blink: I toggle a blinkStatus variable on/off
In -cellForRowAtIndexPath:, I set the image depending upon the blinkStatus
Now, I also call [myTableView reloadData] in the -blink: method, so thinks get updated.
This seems to make sense; the state of the cells is actually changing (the image is being changed), so having the table update makes sense.
This works. However, the reloadData seems to interfere with the user interaction:
In table editing mode if the user selects (-) to delete, and the Delete button appears, it will disappear when reloadData occurs. It's easy enough only do the reloadData if [myTableView.editing] is false. (And it's not a big problem to not have blinking during editing mode.)
However, the reloadData still seems to mess things up (e.g. clear cell selection). I also worry about the efficiency of calling reloadData every .5 seconds.
Is there a smoother way to get that image blinking? I was thinking of saving a pointer to any blinking cells, and update the .image property in the timer. But this seems like a bad idea, since cells are reused for different rows of the table (ouch), and I doubt that simply updating the .image property would update the table without a reloadData.
You should just toggle the image in the -blink method, as long as you use the proper interfaces ( such as cell.imageView.image ) then the image will update automatically, no need to call reloadData
Did you try to use [UIImageView animationImages] property?
Just provide your images, set required duration and animationRepeatCount and call startAnimating

Prevent updates to NSFetchedResultsController whilst table view is in edit mode

I am using an NSFetchedResultsController with a data source that is updated in the background. This is working really well - as new objects are saved to the managed context they appear in the UITableView. However, this leads to the problem I'm having.
When you swipe to delete a cell, putting the cell into edit mode, if at that point an object is created which pushes the cell down in the table view, the position which the cell occupied will be in edit mode, and not the cell you selected. Basically, the UITableView retains the edit mode on the original index path, without adjusting for the movement of cells.
Is there any way to get around this? Thus far everything I've tried has lead to a dead end.
reminds me of a problem i had when reordering uitableview cells.Look at 'Responding to changes' in NSFetchedResultsController reference. It shows a way to temporarily disable the change notification. I used it for reordering, maybe you can get inspiration from it to solve your problem too.
kind regards
y

How to remove cells that can be reused in UITableView (MonoTouch)

We have a scenario where we reuse the same UITableView to display different sets of records from the database as a user selects an item in a different UITableView (similar in concept to a splitviewcontroller, but all in the same view).
When the user selects a different area to view, we fetch the appropriate records from the database, update the Source with the new set of records, and call ReloadData.
The problem is that some of the cells in the UITableView still exist and are reused when switching between lists, resulting in invalid or overlapped data for various rows.
The question I have is: is there a method whereby we can tell the UITableView to discard all existing cells including those queued for reuse? I would have expected ReloadData to perform this task, but it does not.
Update with additional clarification:
Each cell in our table is composed of a variable number of subviews (we are trying to mimic a grid control). When the user selects a different list in the left-hand navigation, there is no guarantee that the subview positions (columns) in the newly selected list will overlap with those in the previous list. This is why we are looking for a method to remove the queued cells.
Since this is a situation that others may find themselves in, I will post the solution that we used, but am still interested in more "native" ways of doing this.
Here is how we solved the issue:
When the set of records being displayed is changed, we update the UITableView with a unique identifier for the current cell configuration (i.e. which list of data is the user currently viewing).
We then created a custom version of UITableViewCell and record the unique list identifier in the cell when it is created.
When we dequeue a reusable cell, we compare the view's current unique identifier with the unique identifier stored in the cell and, if they don't match, we discard the cell and create a new one.
Hopefully this will help someone down the road.
ReloadData does not clear the re-use queue. It simply triggers the callbacks to re-read the data which reloads the rows. As each cell get's loaded, if you're getting it out the re-use queue it will still be used. That's good even if the table view is re-used because the cell types are the same type especially since you use the CellIdentifier to ensure that.
But, it's kind of odd that you're overlapping data. When you get a cell out of the re-use queue, how are you putting the data in it? Are you painting the data directly on the cell? Are you adding subViews with the data (causing multiple sets of overlapped data)? Typically, a cell contains subviews like text labels and the data is set on them so there's no scenario where data gets overlapped - the subviews of cell just has their data updated ...
Your GetCell method needs to ensure that a dequeued cell is fully configured with the new data that it is going to display.
A common mistake is assuming that just dequeuing the cell for display will give you a fresh cell that you can use.
If you have done any customization with your cell, like adding views, modifies its properties (images, disclosure indicators, background colors) you must make sure in the GetCell method that is reusing a cell that every single one of those properties is properly set before returning the cell.

UITableView cell reuse causing NSTimer problems

I have a UITableView with a custom cell I built. The cell has several labels, a start button and a stop button, and an NSTimer that gets fired off and stopped from the buttons.
The labels display data from sqllite (through core data) and the timer runs individually for each separate cell.
This all works fine until I have more cells and cell reuse gets triggered. At that point, each cell shows the correct data in its labels, but if I start a timer for the first cell, the moment it rolls off screen, the next cell showing (and subsequently reusing the previous cell) will have its timer going as well.
I can't figure out how to guarantee each cell has its own timer thread with cell reuse.
Any help would be appreciated.
In your case the cells have internal state (timer). When cell is reused, it's state is lost (or even worth reused cell will inherit previous state). You have two options
don't reuse cells
make cells stateless (e.g. move your timers to controller)