CoreStore icon indicating copy to clipboard operation
CoreStore copied to clipboard

iOS 13 UITableViewAlertForLayoutOutsideViewHierarchy Warning

Open tosbaha opened this issue 5 years ago • 2 comments

I was using ListMonitor delegate to update the tables

func listMonitorWillChange(_ monitor: ListMonitor<KargoCD>) {
   tableView.beginUpdates()
}
    
    func listMonitorDidChange(_ monitor: ListMonitor<KargoCD>) {
        let limit = UserService.sharedInstance.userTotalLimit
        let kargos = Storage.userParcels(limit:limit)
        WatchSessionManager.sharedManager.send(kargos: kargos)
        tableView.endUpdates()
    }
    
    
    func listMonitorDidRefetch(_ monitor: ListMonitor<KargoCD>) {
        tableView.reloadData(effect: .roll)
    }
    
    func listMonitor(_ monitor: ListMonitor<KargoCD>, didInsertObject object: KargoCD, toIndexPath indexPath: IndexPath) {
        SpotlightDataManager.addToSpotlight(object)
        tableView.insertRows(at: [indexPath], with: .automatic)
    }
    
    func listMonitor(_ monitor: ListMonitor<KargoCD>, didMoveObject object: KargoCD, fromIndexPath: IndexPath, toIndexPath: IndexPath) {
        tableView.deleteRows(at: [fromIndexPath], with: .automatic)
        tableView.insertRows(at: [toIndexPath], with: .automatic)
    }
    
    func listMonitor(_ monitor: ListMonitor<KargoCD>, didUpdateObject object: KargoCD, atIndexPath indexPath: IndexPath) {
        
        if let cell = tableView.cellForRow(at: indexPath) as? KargoListCell {
            configure(cell, with: object)
            SpotlightDataManager.addToSpotlight(object)
        }
    }
    
    func listMonitor(_ monitor: ListMonitor<KargoCD>, didDeleteObject object: KargoCD, fromIndexPath indexPath: IndexPath) {
        SpotlightDataManager.removeFromSpotlight(identifier: object.trackingID)
        tableView.deleteRows(at: [indexPath], with: .automatic)
    }

Starting with iOS 13, I started to get following warning on the console. When I put a symbolic breakpoint as the warning says I see that it's generated in didInsertObject delegate call.

[TableView] Warning once only: UITableView was told to layout its visible cells and other contents without being in the view hierarchy (the table view or one of its superviews has not been added to a window). This may cause bugs by forcing views inside the table view to load and perform layout without accurate information (e.g. table view bounds, trait collection, layout margins, safe area insets, etc), and will also cause unnecessary performance overhead due to extra layout passes. Make a symbolic breakpoint at UITableViewAlertForLayoutOutsideViewHierarchy to catch this in the debugger and see what caused this to occur, so you can avoid this action altogether if possible, or defer it until the table view has been added to a window. Table view: <UITableView: 0x11e100600; frame = (0 0; 375 603); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x2819ed5f0>; layer = <CALayer: 0x2817776a0>; contentOffset: {0, 0}; contentSize: {375, 0}; adjustedContentInset: {0, 0, 0, 0}; dataSource: <App.MyList: 0x11dd67520>>

tosbaha avatar Jan 10 '20 13:01 tosbaha

It's as the error says, you have events happening before the UITableView was added to the view. You can try calling ListMonitor.addObserver() only after your tableView is added to the view (usually viewDidLoad)

JohnEstropia avatar Jan 11 '20 07:01 JohnEstropia

The thing is, I am adding Storage.kargos.addObserver(self) in my viewDidLoad. My Tableview is added to ViewController via storyboard. It is a classic Master Detail View application. I add new object in DetailView and call self?.navigationController?.popViewController(animated: true) and I get above warning.

tosbaha avatar Jan 11 '20 08:01 tosbaha