首页 > 解决方案 > Xcode:带有 UICollectionView 问题的 AutoLayout/Storyboard

问题描述

简短的问题: Xcode 中 Storyboard 上的“查看为”功能与您的应用程序在模拟器中的视觉显示方式之间是否存在相关性?


长问题: 我正在开发一个 Schedule 应用程序,在该应用程序中,ViewController 顶部有一个 CollectionView,可让您选择加载日程表的日期,即您可以选择明天来计划您的日程安排,您可以选择今天、昨天或过去或未来的几天。

在我的项目中,我有这个代码来选择当前日期。

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

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

现在,当我运行项目时发生了奇怪的事情。如果我在 Storyboard 中选择 iPhone 11 作为“查看方式”,如下所示:

在此处输入图像描述

然后运行 ​​iPhone 11 Simulator,我的 App 工作正常,它看起来像这样: 在此处输入图像描述

现在,如果我在 Storyboard 中选择 iPhone SE:

在此处输入图像描述

然后在 iPhone 11 上运行该应用程序,它看起来像这样(不工作,不显示“今天”):

在此处输入图像描述

现在奇怪的事情发生了,如果我现在选择 iPhone 8,它的尺寸与 iPhone SE 相同,但仍然在情节提要中选择了 iPhone SE。如您所见,它现在可以工作了:

在此处输入图像描述

如果我还在“查看为”部分中选择了 iPhone SE,并尝试在我的物理 iPhone XS 上运行它,我会遇到同样的问题。

所以我的问题是,这是一个 Xcode 错误吗?假设我在 Appstore 上发布了这个应用程序,它只能在某些设备上运行吗?有没有办法防止这种情况?

在这里,我在 GitHub 上发布了一个 Minimal Reproducible Example:

github.com/julianboyko/Power-Planner-MRE

我几乎可以肯定这是一个故事板问题,这与我必须使用的 StackView 和使用的约束有关。

谢谢你。

标签: iosswiftxcodeautolayoutstoryboard

解决方案


问题是您正在调用:

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

inside viewWillAppear(),此时自动布局尚未确定帧。

相反,您需要在布局完所有视图后调用它。注释掉你的整个viewWillAppear()函数,然后这样尝试:

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

推荐阅读