Search code examples
iosswiftxcodeautolayoutstoryboard

Xcode: AutoLayout/Storyboard with UICollectionView Issue


SHORT QUESTION: Is there a correlation between the "View As" functionality on the Storyboard in Xcode and the way your App appears visually in the simulator?


LONG QUESTION: I'm working on a Schedule app, and in the app there is a CollectionView at the top of the ViewController that allows you to select a date to load a schedule for i.e you can select tomorrow to plan your schedule, you can select today, yesterday or days further in past or future.

In my project, I have this code in place, to select the current date.

override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(true)

        dateCollectionView.selectItem(at: IndexPath.init(item: CalendarModel.CURRENT_DAY, section: 0), animated: true, scrollPosition: .centeredHorizontally)
}

Now, the weird thing occurs when I run the project. If I select the iPhone 11 as the "View as" in the Storyboard like this:

enter image description here

And then run the iPhone 11 Simulator, my App works and it looks like this: enter image description here

Now, if I select the iPhone SE in the Storyboard as such:

enter image description here

And then run the app on the iPhone 11, it looks like this (not working, not showing "Today"):

enter image description here

Now the strange thing occurs, if I now select the iPhone 8, which is the same size as the iPhone SE while still having the iPhone SE selected in the storyboard. It'll now work, as you can see:

enter image description here

If I also have the iPhone SE selected in the "View As" section and try and run it on my physical iPhone XS, I get the same issue.

So my question is, is this an Xcode bug? And let's say I hypothetically released this App on the Appstore, would it only work on some devices? Is there a way to prevent this?

Here I have posted a Minimal Reproducible Example on GitHub:

github.com/julianboyko/Power-Planner-MRE

I'm almost certain it's a Storyboard issue, that has something to do with the StackView I have to use, and the constraints used.

Thank you.


Solution

  • The problem is that you are calling:

    dateCollectionView.selectItem(at: IndexPath.init(item: CalendarModel.CURRENT_DAY, section: 0), animated: true, scrollPosition: .centeredHorizontally)
    

    inside viewWillAppear(), at which point auto-layout has not yet determined the frames.

    Instead, you need to call it after all the views have been laid-out. Comment-out your entire viewWillAppear() func, and try it this way:

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        dateCollectionView.selectItem(at: IndexPath.init(item: CalendarModel.CURRENT_DAY, section: 0), animated: false, scrollPosition: .centeredHorizontally)
    }