iOS 13 UITableViewAlertForLayoutOutsideViewHierarchy Warning #306

Open
opened 2025-12-29 15:28:31 +01:00 by adam · 2 comments
Owner

Originally created by @tosbaha on GitHub (Jan 10, 2020).

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>>

Originally created by @tosbaha on GitHub (Jan 10, 2020). I was using `ListMonitor` delegate to update the tables ```swift 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>>
adam added the questionuser bug labels 2025-12-29 15:28:31 +01:00
Author
Owner

@JohnEstropia commented on GitHub (Jan 11, 2020):

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 commented on GitHub (Jan 11, 2020): 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`)
Author
Owner

@tosbaha commented on GitHub (Jan 11, 2020):

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 commented on GitHub (Jan 11, 2020): 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.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/CoreStore#306