Search code examples
iosipadviewdidlayoutsubviews

moving app to background, calls viewDidLayoutSubView and create a lot of warnings with UICollectionView


it's all start from a lot of warnings about the width of collectionView cells, That was written to console every time I press home button.

I thought it's something with size of the cells and tried to fix it. Only after some testing, I notice that viewDidLayoutView is called with wrong view.bounds, and that make the collectionView cell bigger(in width) than collection view.

For now, my fix is to check if app is on background state and ignore viewDidLayoutView.

  1. why it's happen only in iPad and not on iPhone ?
  2. it's whirred that only now I saw this happening. it's something new in iOS ?
  3. what is the right way to handle this ? I don't use auto-layout
  4. its calling with wrong bounds and I don't want to calculate all cells frames just for the user to return to the same orientation.
  5. I feel like I'm missing something very basic here OR there is some change on iOS that I'm not aware.

Solution

  • why it's happen only in iPad and not on iPhone ?

    Because when you click Home on an iPad and the app goes into the background, the runtime takes two snapshots, one in each orientation, to use in the App Switcher interface (and in preparation for when the app comes back to the front). That means it has to rotate the app, which triggers layout, and so your viewDidLayoutSubviews is called.

    it's whirred that only now I saw this happening. it's something new in iOS ? what is the right way to handle this ? I don't use auto-layout its calling with wrong bounds and I don't want to calculate all cells frames just for the user to return to the same orientation. I feed like I'm missing something very basic here OR there is some change on iOS that I'm not aware.

    Well, iPads have been behaving like this for quite a long time. It isn't my job to explain why you haven't noticed. Basically you should not be doing anything time-consuming in viewDidLayoutSubviews.

    for now, my fix is to check if app is on background state and ignore viewDidLayoutView

    That's perfectly reasonable. I do the same sort of thing. For example (this is a different method, but it's the same idea):

    override func viewWillTransition(to size: CGSize, with tc: UIViewControllerTransitionCoordinator) {
        if UIApplication.shared.applicationState == .background {
            return
        }
        // ...
    }
    

    Be warned, however, that if you are doing manual layout and you don't do it when the app when goes into the background, your App Switcher snapshots may look wrong. Also, the fact that you are not using autolayout is a red flag. You should probably use it.