Blinking image in table cell - objective-c

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

Related

iOS7 UITableview slow on reloading section/row

My tableview that used to smoothly reload the sections and rows is now slow when running on iOS 7. When I reload the whole tableview table is loaded instantaneously, but calling reloadRowsAtIndexPaths or reloadSections (with UITableViewRowAnimationNone) takes somewhere around a second to complete.
I'm not using AutoLayout for this section of the app yet. The cells are laid out in separate Xib files with the corresponding custom classes
Do you have auto layout enabled for your cell views? Are you reloading your table view when it is not visible (for instance, when a detail view controller is pushed)? This seems like a known bug. See this question/answer. Apple bug report: rdar://15175803
Basically, you have a multi tiered solution, which is not perfect but will give you satisfactory results. First, this is always true, optimize your constraints in the table view cell. If you have constraints modified dynamically, make sure you are not causing needless layouts and drawing. Second, do not update your table view if it is not visible. This feels like a hack, but there is no other option (well, there is one, but it involves disabling auto layout, which is not optimal at all, so let's ignore). You can test in your view controller if the tableView.window property is nil, which would indicate that the table view is hidden. If it is not hidden, update normally, but if it is, do not update. Just set a flag that the table was updated. On viewWillAppear: call reloadData to update the table. You can preserve selection by querying the table view for selected indexpaths and selecting them again after reloading the data.

UITableViewCell Height Calculation and delegation?

I know this question had been asked hundreds of times before, but it's never really been solved (Or at least the way I'd like it to be). I have a rather complex UITableViewCell setup. The cell.backgroundView is loaded from a UIView subclass which uses a fair bit of CoreGraphics and CoreText. The code is rife with CTFramesetterSuggestFrameSizeWithConstraints, so I'm relectant to duplicate the class in the heightForRowAtIndexPath method.
I think I can solve this by creating an NSMutableDictionary with the indexPath as the key and the height as the value. But then I'm faced with the problem of heightForRowAtIndexPath being called first. I believe I can solve this problem by guessing the height of the cell and then once the cell's UIView subclass has finished rendering, use delegation to set the cell's height.
But this leaves me with the problem, how the hell do I delegate this? And, how to I prevent scrolling from being extremely choppy? as the cells will be created and resized in a split second.
In the past, I've used a dummy cell. I have a separate method -fillInCell:forRowAtIndexPath: which puts data into the cell. That way I can fill out the dummy cell in -tableView:heightForRowAtIndexPath: and the real cell in -tableView:cellForRowAtIndexPath:.
If this does not work for you then there are other options.
The first thing that comes to mind is create real cells in -tableView:heightForRowAtIndexPath: instead of -tableView:cellForRowAtIndexPath:. You can store completed cells in a mutable dictionary. -tableView:cellForRowAtIndexPath: will simply pull the completed cell from the dictionary. You should also detect when scrolling has stopped so you can empty your dictionary (just because -tableView:heightForRowAtIndexPath: was called doesn't mean -tableView:cellForRowAtIndexPath: will get call for the same indexPath).
Hope that helps.

Value is shown in UITableView after it is scrolled

In my iPad application, I am inserting some value on a label. That value should also appear on a UITableView in another class. When I insert the value in the label and navigate to another view, there is no value appearing on the table view but when I scroll the table view up and as it comes to its original position, the value appears. How can I fix it?
Thanks and regards
PC
When you scroll the table you are eventually reloading the data as things become visible. If you call [tableView reloadData] on viewillAppear this should get the label refreshed and displaying correctly for you.
Good Luck!
Check out the reloadData method in the documentation. You will need to call this method after changing the value so the table knows to reload the cells currently being displayed. As you scroll up the cells are being redrawn, which is why you see the new value after a scroll.
Just to clarify, the reloadData method will need to be called on the UITableView object.
[myTableView reloadData];
From the documentation:
Reloads the rows and sections of the receiver.
- (void)reloadData
Discussion
Call this method to reload all the data that is used to construct the table, including cells, section headers and footers, index arrays, and so on. For efficiency, the table view redisplays only those rows that are visible. It adjusts offsets if the table shrinks as a result of the reload. The table view's delegate or data source calls this method when it wants the table view to completely reload its data. It should not be called in the methods that insert or delete rows, especially within an animation block implemented with calls to beginUpdates and endUpdates

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

UITableView :cellForRowAtIndexPath Continues being called

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.