我有一个相当简单的构造,在我尝试将 Swift 语言版本切换到 6.0 之前它一直运行良好:
private struct SomeHeightKey: EnvironmentKey {
static var defaultValue: CGFloat { UIScreen.main.bounds.size.height }
}
public extension EnvironmentValues {
var someHeight: CGFloat {
get { self[SomeHeightKey.self] }
set { self[SomeHeightKey.self] = newValue }
}
}
现在似乎存在一个关于
defaultValue
的问题:无法从非隔离上下文中引用主要参与者隔离类属性“main”。
显然,EnvironmentKey
协议要求它是nonisolated
以维护协议一致性。
我花了几个小时与 ChatGPT 和 Copilot 一起尝试找到解决此问题的并发安全方法,但到目前为止还没有运气。我在这里缺少什么?我正在寻找在 Swift 6 中执行此操作的正确方法以及任何允许我推迟修复它的解决方法,但仍将其余代码库迁移到 Swift 6。
最终该值用于 ScrollViewWrapper:
public struct ScrollViewWrapper<Content: View>: View {
let content: () -> Content
public init(@ViewBuilder _ content: @escaping () -> Content) {
self.content = content
}
public var body: some View {
GeometryReader { proxy in
ScrollView {
content().frame(minHeight: proxy.size.height)
}
.frame(height: proxy.size.height)
.environment(\.someHeight, proxy.size.height)
}
}
}
这是继承的代码,我正在尝试迁移 - 我不是 SwiftUI 的专家,我什至不确定他们试图在这里完成什么。但也许答案是找到一种完全不同的方法......
如果您总是使用
.environment(\.someHeight, proxy.size.height)
设置环境值,则默认值并不重要,因此您可以将其设置为某个常量值:
static let defaultValue: CGFloat = 0
在 Xcode 16 中,您还可以删除
SomeHeightKey
并直接使用 Entry
扩展中的 EnvironmentValues
宏:
extension EnvironmentValues {
@Entry var someHeight: CGFloat = 0
}
如果您确实需要使用主要参与者隔离值作为环境键的默认值,您可以将其设置为视图层次结构根部的环境值。
var body: some Scene {
WindowGroup {
ContentView()
}
.environment(\.someKey, someMainActorIsolatedValue)
}
但我不会用
UIScreen.main.bounds.height
这样做。如果您需要知道视图有多少可用空间,请使用如您所示的 GeometryReader
。大多数时候,您甚至不需要几何阅读器,因为还有许多其他修改器可以帮助您布局视图,例如 containerRelativeFrame
。