keyWindow?.bounds.size is nil at first load: Swift iPadOS 13

I am developing an app for iPad for iPadOS 13.


There are two UICollectionViewController one navigates from one cell to another UICollectionViewController. I am using the following code:


I have declared keyWindow at UICollectionView Controller as:


let keyWindow = UIApplication.shared.connectedScenes
    .filter({$0.activationState == .foregroundActive})
    .map({$0 as? UIWindowScene})
    .compactMap({$0})
    .first?.windows
    .filter({$0.isKeyWindow}).first


But on first UICollectionViewController 'keyWindow?.bounds.size' gets printed as nil but on second UICollectionViewController same iPad Simulator 'keyWindow?.bounds.size' it gets printed as 'Optional((768.0, 1024.0))'. I am using the exact same code everywhere.


func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
     var sizeArea = CGSize()
     print("UIScreen.main.bounds.size \(UIScreen.main.bounds.size)")
     print(keyWindow?.bounds.size)
     if UIScreen.main.bounds.size == keyWindow?.bounds.size {
     print("UIScreen.main.bounds.size == keyWindow?.bounds.size")
     let spacing = self.view.frame.size.width - 25
     let itemWidth = spacing / 4
     sizeArea = CGSize(width: itemWidth, height: itemWidth)
} else {
     print("else")
     let spacing = self.view.frame.size.width - 20
     let itemWidth = spacing / 3
     sizeArea = CGSize(width: itemWidth, height: itemWidth)
}
}


What I am doing wrong here?

Accepted Reply

Is it a Simulator problem?

I don't think so. If your code `let keyWindow = ...` is evaluated when there is no keyWindow yet, 'keyWindow?.bounds.size' becomes nil.

I thought that it was ready in `collectionView(_:layout:sizeForItemAt:)`, but seems that was wrong.


You may need to find some timing when keyWindow is ready, and then reload your collection view.

Have you tried viewDidAppear ?


By the way, do you really need 'keyWindow?.bounds.size'? Can't you use for example `self.view.bounds.size` instead?

Replies

What I am doing wrong here?

That depends on when you put the code `let keyWindow = ...`.

Your view controller may be instantiated when no scene is .foregroundActive, or no window is active.

In such cases `keyWindow` would be nil.


Try moving that `let keyWindows = ...` into the method `collectionView(_:layout:sizeForItemAt:)`.

I tried moving 'let keyWindow' to 'SizeForItem' but it did not helped... it is still 'keyWindow?.bounds.size' is nil...


I even tried printing 'keyWindow?.bounds.size' from 'ViewDidLoad' and it is still nil...


Is it a Simulator problem?

Is it a Simulator problem?

I don't think so. If your code `let keyWindow = ...` is evaluated when there is no keyWindow yet, 'keyWindow?.bounds.size' becomes nil.

I thought that it was ready in `collectionView(_:layout:sizeForItemAt:)`, but seems that was wrong.


You may need to find some timing when keyWindow is ready, and then reload your collection view.

Have you tried viewDidAppear ?


By the way, do you really need 'keyWindow?.bounds.size'? Can't you use for example `self.view.bounds.size` instead?

Your code worked: 'self.view.bounds.size'