SwiftUI: 在使用 Xcode 12 beta 2 构建 iOS 13 和 iOS 14 时,使用 if #available 时出现错误

5

我想让我的应用程序能够在iOS 13(实际上我希望是iOS 13.5)和iOS 14上部署,因此我编写了以下代码进行测试:

struct ContentView: View {
    var body: some View {
        if #available(iOS 14.0, *) {
            List {
                Text("Cool!")
                Text("Cool!")
                Text("Cool!")
                Text("Cool!")
            }
            .listStyle(InsetGroupedListStyle())
            
        } else {
            List {
                Text("Cool!")
                Text("Cool!")
                Text("Cool!")
                Text("Cool!")
            }
            .listStyle(GroupedListStyle())
            .environment(\.horizontalSizeClass, .regular)
        }
    }
}

构建 iOS 14 版本很顺利,但是当我在真实手机和模拟器上构建 iOS 13.5 版本时,在 AppDelegate 中会出现以下错误:

Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)

我已经确保将iOS部署目标设置为iOS 13.5,并且正在使用Xcode 12 beta 2。我尝试过使用beta 1,但结果相同(可能是因为我使用的是同一文件?)。我不确定我是否做错了什么或者这是否是一个错误。当仅使用iOS 13.5的代码(没有if#available)时,它可以正常工作,但仅当我添加该检查器时,我的问题才会出现。任何帮助都将不胜感激!


是的,我可以重现。好的说明! - matt
2
如果我是你,我会提交一个错误报告。断点显示我们在iOS 13上没有进入条件的第一个部分。如果你只注释掉.listStyle(InsetGroupedListStyle()),我们就可以在iOS 13上编译和运行良好,证明这是问题的根源。但仅仅存在这个修改器,并没有实际执行,不应该导致崩溃。你不能通过条件编译来解决问题,因为你无法测试版本。 - matt
当我移除了listStyle,它也为我解决了问题,这很奇怪!我已经提交了一个错误报告,希望它能很快得到修复! - Jabinator1
也许在这里不允许使用 if,但你会认为编译器会报错。 - matt
@matt 是的,我尝试了很多方法,但还没有找到解决办法! - Jabinator1
2个回答

7

很不幸我无法在Xcode 12 beta 4中重现这个bug,所以提供一个解决方法。您可以将iOS 14的代码包装到AnyView中,这样所有内容都可以成功编译。在这种情况下,您可以使用ViewModifier使代码看起来更加Swifty。

struct ContentView: View {
    var body: some View {
        List {
            Text("Cool!")
            Text("Cool!")
        }
        .modifier(GroupedListModifier())
    }
}

struct GroupedListModifier: ViewModifier {
    func body(content: Content) -> some View {
        Group {
            if #available(iOS 14, *) {
                AnyView(
                    content
                        .listStyle(InsetGroupedListStyle())
                )
            } else {
                content
                    .listStyle(GroupedListStyle())
                    .environment(\.horizontalSizeClass, .regular)
            }
        }
    }
}

2

这个问题应该在Xcode 12 beta 5及以后的版本中得到修复。如果没有,可以使用反馈助手报告此问题。

对于那些好奇的人,问题在于即使在iOS 13设备上没有采用iOS 14分支,SwiftUI仍然会处理由该分支生成的视图类型,而其中一些类型在iOS 13中不存在。@pacification建议的AnyView解决方法之所以有效,是因为它隐藏了iOS 14分支中的类型信息,除非采用该分支,否则SwiftUI不会处理它。实际上,Xcode 12 beta 5通过自动将if #available分支包装在AnyView中基本上解决了这个问题。


太酷了,感谢这个解释!听起来像是某种急切的优化让我们出了点问题。很酷的 bug,不是吗? - matt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接