How to avoid iOS UITableView animation to block user interaction with table - ios

I have a timer that insert a new item on a tableview every 2 seconds, it is required that the tableview shows this new line insertion with an animation of 1 second, the problem is that the user interaction is blocked while the tableview insert animation is happening, I tryied to pass as option for the animation the constant UIViewAnimationOptions.AllowUserInteraction, but it did not worked. What I need is that the user can interact with the tableview, selecting cells, scrolling etc even during the animation sequence. Any ideias ? The code for the problem example is on github
https://github.com/munhra/TableAnimationProblem
This video shows the not desired behavior
https://www.youtube.com/watch?v=Jb7dnCv5wXw&feature=youtu.be

Related

Override UIAccessibilityLayoutChangedNotification when UICollectionView changes layout

I'm trying to enable VoiceOver accessibility on my collection view which behaves as follows:
Upon selection of an item, it will remove the rest of the items in the section, leaving only the item that was selected.
When I select the item again, it will re-populate the section with the items that was previously removed.
For step 1, voiceover reads out the item just fine, and it'll be the focus after the layout change.
However, for step 2, things get a bit weird. It'll start reading out the item, and just before it finishes, the focus jumps to another item, and begins reading that one instead.
From Apple's documentation about collection views, it automatically posts a layout change notification when a layout occurs. But, from the looks of it, it's passing on some random element to the first focus element after the layout change.
When a collection view changes its onscreen layout, it posts the UIAccessibilityLayoutChangedNotification notification.
Is there anyway to override this automatic layout changed notification, so that I can pass in the correct focus element?
I found the reason for what was happening.
The reason an element was randomly focusing was because I was calling reloadData on the collectionview in the performBatchUpdate's completion block.
Removing the reloadData solved this problem. However, because I'm not calling reloadData, I had to call reloadItemsAtIndexPaths on specific cells, which is fine in my case.

UITableview does not immediately respond to cell selection

I have a tableView where each cell triggers a modal view (it is a travel planner, the table is used to select origin and destination).
After selecting an address the modal is dismissed and the user is returned to the tableview. However, if I immediately select a cell the event is not recoginized, I need to wait a few seconds.
I've checked that neither shouldHighlightCellAtIndexPath or didSelectCellAtIndexPath is called.
After checking other questions here I also tried to set delaysContentTouches to false (for tableview and the embedded scrollview, see UIButton not showing highlight on tap in iOS7)
Do anyone know how I can make the tableview respond to selection immediately? The delay is just long enough to annoy the users
First of all on tap on UITableViewCell, delegate that gets called is didSelectRowAtIndexPath. This gets triggered instantaneously - always!
My guess is you are doing some networking on your main thread on tap on cell and then presenting new screen with that data. This would make UI look delayed and un-responsive. Please double check and ensure all non-UI stuff that need not require main thread goes in a parallel thread.

How do I perform cell selection animations while using reloadData?

I have a UICollectionView, and I override setSelected in the UICollectionViewCell subclass to perform a little bounce animation when the user selects the cell.
The problem is that on selection of the cell, the very selection of the cell alters the data for the other cells (for instance, imagine the other cells have a label in each one that has the amount of cells selected displayed). So I call collectionView.reloadData() so that all the other cells update as well to show the new data (for instance, the amount of cells selected in a label).
However, this reloadData() call seems to reset the UICollectionView completely. Any animations taking place are stopped and the cells are simply updated without animation.
How do I have the cell selection animation, and update the other cells at the same time?
I've tried calling reloadData() only after the animation has completed, but this makes it look like there's lag/delay in updating the other cells (as it doesn't update them until a moment after when the animation finishes), which doesn't look very good.
Similarly, I've tried calling reloadItemsAtIndexPaths: (and exclude the selected cell that will animate), but for whatever reason with collection views this method seems really slow. Like there's a noticeable amount of lag after pressing it.
What should I be doing here? What's the standard for reloading data without the collection view destroying in-progress animations?
Reloading throws away the existing cells and creates (or reuses) new ones. So any animation is inherently destroyed. So, don't reload.
Instead, update your data model as usual and then get the currently visible index paths and associated cells and directly update those cells.

UICollectionView insertItemsAtIndexPaths: seems to reload collectionview or autoscrolls to top

I am using a UICollectionView in combination with a NSFetchedResultsController. When I fetch new data, I throw them in a SQLite database and my frc gets a notification that it will update. I implement the appropriate delegate methods and insert the new data in a batch update and I don't call reloadData afterwards. But as soon as the data is inserted, the collectionview scrolls to the top (to make the new items visible?). I would like to interfere this process and imitate the Facebook/9Gag implementation. When there is new data, a button is faded in which lets the user scroll to the top. At the time the button is shown, the new items are already inserted, so the user can also just scroll up himself. I tried the following:
hooking into the UIScrollViewDelegate methods to see if I could stop the collectionView from scrolling (none of the methods is called during this update process)
show the "scroll to show more"-button when the frc willUpdate and just insert the items when the button is pressed. The problem is that the user cannot scroll up himself
Before inserting the items, I calculate the indexPath of currently visible items AFTER the insertion (adding the number of inserted items) and scroll to that index without animation in the completion block of the batch update. This only works if I delay the scrolling, but then it flickers, because it's first scrolling up a little
I experimented the same problem, by calling "insertItemAtIndexPaths" to increment data into my collectionView.
I noticed two things :
- If you add items AFTER the current visible index path, there's no automatic scroll
- If you add items BEFORE the current visible index path, there's no automatic scroll, like you said, but the contentOffset is kept at the same position, but with different contentSize, because you've just added new items.
To deal with this "side effect", I used the solution mentioned here : UICollectionView insert cells above maintaining position (like Messages.app)
As it's explained in the following post, the "CATransaction.setDisableAction(false)" is the key thing to update smoothly the contentOffset position.

Allowing selection while reloading UITableView section

I have a basic tableview with section headers that contains cells. A cell either has a checkmark visible or not. When the user selects the cell, it toggles the checkmark, and if all items in that section has the checkmark visible, additionally the section header is greyed out.
I trigger the UI update in tableView:didSelectRowAtIndexPath: by first updating the model and then call reloadSections:withRowAnimation:UITableViewRowAnimationAutomatic on the relevant section.
The problem is that when animating the change (duration about 0.3 s), the user cannot select another row until the animation is done. It is a common usage scenario, wanting to check a number of items in batch. I also absolutely want to animate the change.
The documentation states that one can configure a UIAnimation using UIViewAnimationOptionAllowUserInteraction to remedy this, but since I'm not using a manual UIAnimation but only calling UITableViewRowAnimationAutomatic, I don't know how to accomplish this.
Is there a way to allow the user to select (and initiate animations) on other cells while such an animation/reload is ongoing?
Note
It's tricky to get a custom section header to redraw/animate, the only way I managed to do it is by first reloading the affected section, and then immediately reloading the table – the latter to hide a flicker that appears otherwise.
If I only reload the single affected row, there is not animation on the section header – it just changes.
I ended up disregarding that the section header does not animate, the user experience is more severely affected by not being able to quickly toggle several items in the list.

Resources