What can trigger a UITableView reload? - ios

I'm chasing this weird bug where my UITableView (which is backed by a NSFetchedResultsController) is being reloaded without me explicit asking for it. This UITableView has a UITableViewController as it's controller and a View Model as it's Data Source. The flow works as it follows:
Click the filter button
Filter screen appears
Select one filter
Click Filter button
tableView from presentingViewController is reloaded
Filter screen disappears
Now I know, some things can trigger the reload in this scenario:
A call to any of the reload functions (row/section)
NSFetchedResultsController delegate being called
None of these are true. The only thing that happens is the dismissal of the Filter List Screen - which is triggered by the Filter button:
#IBAction func filterButtonAction(sender: AnyObject) {
self.presentingViewController!.dismissViewControllerAnimated(false, completion: nil)
}
Note that the UITableView reloading is only happening after calling filterButtonAction, not before. This indicates that's something related to UIViewController's callbacks (viewWillAppear etc), but there's not a single reloadTable to be found (and I don't even implement viewWillAppear on the presentingViewController).
What could be triggering the tableView reload here? Is there a way to trace a call to the tableView data source?

Turns out this is an iOS 8 issue - I started testing in an iOS 7 device, and reloadTable wasn't called at random.

Related

Swift - Tableview reloads only after second tap of the tab bar

I've read 3 pages of google results and none worked for me, here's detailed description of the problem:
Every time I launch my app If I tap on the tab bar item that shows the vc that contains my table view it is empty. I have to go to another tab and return to it, just then my table view fetches. Spent 8h trying to fix it already.
Same exact VC shown with a button tap is displayed correctly and loads every time.
What i've already tried:
triple checked if I have:
tableView.delegate = self
tableView.dataSource = self
Tried moving the fetching to viewDidAppear or viewWillAppear, none worked.
Diagnosed it, number of sections is returned but number of rows = 0, cellForRowAt never executes on first tab bar click, even tho my posts are fetched correctly.
Tried fixing any constraints that exist, didn't work.
It simply seems like tableView.reloadData() doesn't work. I surrender, please help me!
You still haven’t provided a very clear picture. At a glance, though, I’d say you need to add a call to your table view’s reloadData() method inside the braces on your call to posts(for:completion:). (I’m guessing about the exact name of that function since you don’t include it.)
If your posts(for:completion:) invokes its completion handler on a background thread then you’ll need to wrap your call to reloadData() in a call to DispatchQueue.main.async() (Since TableView.reloadData() is a UIKit call and you can’t do UIKit calls on a background thread.)
The code might look like this:
StartTestingViewController.posts(for: UUID as! String) { (posts) in
DispatchQueue.main.async {
self.posts = posts
self.tableView.reloadData()
}
}
(I didn’t copy your whole viewDidLoad method, just the bit that calls your function that fetches posts.)
The UITableView.reloadData() method tells your table view “The number of sections/rows of data or their contents may have changed. Please re-ask your data source for contents and re-build your cells.” The table view will ask for the number of sections again, ask for the number of rows in each section, and ask for enough cells to fill the table view’s frame with cells.
If you don’t call reloadData() your table view has no idea that there is new data so it doesn’t reload itself.
I suspect that the reason that you can go another tab and come back and see your data is that the data has been loaded while you were on another tab, and so is available immediately. I’d have to see the exact details of your tab displaying code to be sure.

UITableView Cells Disappear after Dismiss View That I Add

I'm having a difficult time understanding what I should even be looking for to debug this issue.
I have a UITableView that populates correctly.
I select one of the UITableViewCells which upon selection presents a new view to the user with more detail.
If I click Back on this new window, the original UITableView shows none of the UITableViewCells anymore.
I guess the problem is when you are coming back, your array is being empty somehow. In your first "ViewController" override the "viewWillAppear()" method and print the count of your array in this method. Then load the app and check the print result, then go to second "ViewController" and press the back button and see the print results again. if it shows zero "0" then check your code and try to find out where your array is being empty.
Hope this will help.
I ended up setting the delegate and datasource in the viewDidAppear() rather than the viewDidLoad(). Once I did that, I added a tableView.reloadData() inside of the completion handler for retrieving the data from the API and the tableView was then being populated as expected.

How do display a refreshed view without touching it first?

Well, the title already says it all. I have a view (a table view in my special case embedded in a non-table view controller) and at some time in code I want to update cells and display the update. The first part works like a charm but the changes won't displayed after the reloadData() - and even when I call setNeedsDisplay() afterwards.
When the controller has to update something the tableview will be also re-drawn and the changes are visible. As soon as I touch the tableview cell the changes are also visible. Without touch the update just isn't displayed.
I've come across this issue and using GCD should solve it
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});

Collection view's last focused index path lost after reload data in tvOS

In my tvOS app, I have a collection view where I've set its remembersLastFocusedIndexPath to true. As this is not enough to get this behaviour, I've also overridden a method in my UIViewController like this:
override weak var preferredFocusedView: UIView? {
return collectionView
}
This was working fine until I started reloading the collection view for some reasons. It does work if, being the collection view visible, I call collectionView.reloadData().
This doesn't work, tho, if I do the reload when the collection view is not visible, for example, when I'm in a detail view after tapping one of the items. When I come back to the grid, the focused index path is not the one I tapped.
As a workaround, I'm managing this non-ideal scenario:
As the reload is triggered by fresh data coming from my backend, I only call collectionView.reloadData() when the collection view is visible (because I know that the last focused index doesn't change here).
I call collectionView.reloadData() in viewDidAppear(animated: Bool) to have the latest content available when the user comes back.
How can I do this properly? Thanks in advance.
Recently I got this issue also, my situation is pretty much same to you.
I also called collectionView.reloadData() in viewDidLoad and viewWillAppear
And then
I changed from
collectionView.reloadData()
to
collectionView.reloadItemsAtIndexPaths(collectionView.indexPathsForVisibleItems())
It works for me most of time, there is still approximately <5% chance to mess up the last focus index
One option is to set remembersLastFocusedIndexPath to false, and implement indexPathForPreferredFocusedViewInCollectionView: to achieve the same behavior.

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.

Resources