简体   繁体   中英

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

在此处输入图像描述

And then run the iPhone 11 Simulator, my App works and it looks like this: 在此处输入图像描述

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

在此处输入图像描述

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

在此处输入图像描述

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:

在此处输入图像描述

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.

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

Have you tried to clean your build using cmd+shift+k? It probably won't do anything but couldn't hurt to try. Also on the second screenshot it isn't positioned equally but programmatically set it to center, have you checked all constraints(and again don't know why that would change the displayed style but worth a shot).

The various devices in the simulator each have their own state. Your app may be installed on some of them and not on others, and the app's state on each of the devices on which it's installed is specific to that device.

It looks like your app defaults to showing the current date, but it also saves the selected date and uses that the next time it runs. That'd be pretty reasonable behavior, at any rate, so for the sake of argument let's say that's what it does. If you ran your app on the iPhone 11 simulator last week, then perhaps your app saved that day as the selected date. When you ran it again recently on other devices where it wasn't installed, the app started “fresh” and chose the current date. But when you ran it on the iPhone 11, the app already had some saved data, so it used that instead of falling back to the default behavior.

Note that this will be the case even if you rebuilt the app and installed it again on the iPhone 11 simulator. When you rebuild the app, Xcode installs the new app but leaves the apps'sexisting data in place, just as though you were updating the app from the App Store. If you want the app to launch as though it were newly installed, just delete it from the simulator before building.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM