我正在尝试创建一个视图样式,用于自定义我正在开发的SwiftUI视图。我用makeBody
函数声明了一个协议,我将样式存储为@State
属性,以便可以更新它,并且我从视图内部调用makeBody
。该技术与what SwiftUI already does非常相似,但有一件事我无法理解。
问题
第一方视图样式有一个重要的行为是我无法复制的--那就是在自定义视图样式中使用@State
、@Environment
或任何其他SwiftUI属性 Package 器。
例如,我可以实现下面的自定义ButtonStyle
,它只将当前配色方案的值显示为按钮的内容。
struct MyButtonStyle: ButtonStyle {
@Environment(\.colorScheme) var colorScheme
func makeBody(configuration: Configuration) -> some View {
Text(String(describing: colorScheme))
}
}
struct MyView: View {
var body: some View {
Button("foo", action: {}).buttonStyle(MyButtonStyle())
}
}
当我用.dark
首选配色方案预览MyView
时,MyButtonStyle
的colorScheme
属性被更新,makeBody
函数被再次调用,文本读作“dark”,这都是意料之中的。
现在,让我们看看我创建的自定义视图样式。
struct MyCustomStyle /* : CustomStyle */ {
@Environment(\.colorScheme) var colorScheme
@ViewBuilder func makeBody(configuration: CustomStyleConfiguration) -> some View {
Text(String(describing: colorScheme))
}
}
struct MyView: View {
@State var style = MyCustomStyle()
var body: some View {
style.makeBody(configuration: .init())
}
}
在上面的场景中,当我使用.dark
首选配色方案预览MyView
时,colorScheme
属性没有更新,即使标签的前景色正确地选择了更改,文本也显示为“light”。
问题
如何使@State
和@Environment
属性在自定义视图样式中工作,就像它们在ButtonStyle
和视图中工作一样,而不向makeBody
函数的实现引入任何样板文件?
我确信这是可能的,因为所有第一方视图样式都已经支持这一点,没有样式符合View
,也没有实现私有_makeView
API,该API手动向SwiftUI的图形添加依赖项(至少根据SwiftUI
的模块接口)。
我尝试但没有成功
我试着在一个 Package 了MyView
的视图的可计算body
中初始化视图样式,但也不起作用。
struct ContentView: View {
var body: some View {
MyView(style: MyCustomStyle())
}
}
不可接受的答案
将自定义makeBody
函数的返回值 Package 在单独的视图中,并且colorScheme
属性是该视图的一部分,这是一种已知的变通办法,可产生正确的行为。建议将此作为变通办法的答案将不被接受,因为此问题完全是关于 * 避免这种情况 *。
如果回答说不可能在符合View
的类型之外使用@Environment
或@State
,则将不予接受(因为这是可能的,请参见ButtonStyle
),除非他们能够 * 证明 * 私有API是驱动这一点的原因。
1条答案
按热度按时间yhuiod9q1#
我们无法访问与
ColorScheme
对应的EnvironmentKey
,但是它的defaultValue
必须是light
,这就是为什么你可以在视图之外得到一个值。您的类型实际上不会随
EnvironmentValues
一起提供,除非它是View
、ViewModifier
、ButtonStyle
......Apple实际上并没有提供被视为“视图层次结构的一部分”的协议的详尽列表。您要做的是实现您自己的
Style
,但不幸的是,这目前是不可能的。例如,
ButtonStyle
文档告诉我们,系统为视图层次结构中的每个Button示例调用此方法,其中此样式是当前按钮样式。
以下所有类型都符合相同的配置文件,您可以实现其中的一种样式,但不能创建符合某个父
Style
协议的类型。如果你不遵守其中一个“视图层次结构”协议,那么依赖注入就不是依赖于环境而是依赖于环境。
x一个一个一个一个x一个一个二个x
你必须给予你真正想做的事情,除非你去苹果公司开发SwiftUI。但是,你应该评估一下你是否能摆脱一个有针对性的功能子集。
一个一个三个一个一个一个一个一个四个一个一个一个一个一个五个一个
你的问题也提到了
State
,但是你没有提供一个例子,你可能只需要在使用State
时遵守DynamicProperty
。