英文:
SwiftUI compiler directives trigger "Cannot infer contextual base" error for following statements
问题
我有一个用于watchOS/iOS应用程序的SwiftUI视图,在其中使用#if os(xxxOS)编译器指令来选择特定于watchOS的视图或特定于iOS的视图,以为OSCommonView的body属性提供内容。watchOS和iOS的body视图都调用相同的一组视图修饰符,这些修饰符本身引用了在父OSCommonView中声明的函数。因此,我认为可以使用#if...#else...#endif编译器指令来切换OS特定的子视图视图,然后是修饰符,而不是在每个iso/watchOS子视图中复制这些修饰符。但是,无论哪个修饰符是第一个或最后一个,都会出现“无法推断出上下文基础...”错误。似乎#endif会导致编译器不“看到”第一个修饰符上面的可选视图?
我天真地认为编译器指令是“不可见的”,只是根据切换无缝呈现代码。我尝试创建一个ViewModifier来将它们分组,但未找到将OSCommonView的参数(包括一些绑定)和方法传递到ViewModifier结构的方法。目前,我只是在每个body_watchOS和body_iOS的定义中重复了一长串视图修饰符。
如果我将修饰符放在上面的编译开关内,它们可以正常工作,但这违背了不重复它们的初衷!
有什么建议吗?非常感谢。
英文:
I have a SwiftUI View for a watchOS / iOS app in which I use the #if os(xxxOS) compiler directive to select between a watchOS specific View or an iOS specific View to provide the content for the the OSCommonView body var. Both the watchOS and iOS body views call the same bunch of view modifiers, which themselves reference functions declared in the parent OSCommonView. So instead of replicating those modifiers in each of the iso/watchOS subviews I thought I could use the #if...#else...#endif compiler directives to switch-in the OS-specific subview view, followed by the modifiers. However, I get the error "Cannot infer contextual base for ..." for the first and last modifier, whatever modifier is the first or last. It seems that #endif makes a break such that the compiler does not "see" the optional view above the first modifier??
struct OSCommonView: View {
var body: some View {
#if os(watchOS)
body_watchOS
#else
body_iOS
#endif
.onAppear() { handleOnAppear() } <= Cannot infer contextual base error...
.onDisappear() { handleOnDisappear() }
.onReceive(uiUpdateTimer) { handleReceive_uiUpdateTimer(newDate: $0) }
/* --- several other modifiers --- */
}
var body_iOS: some View {
/* view subviews etc */
}
var body_watchOS: some View {
/* view subviews etc */
}
func handleOnAppear() { /* ... */}
func handleOnDisappear() { /* ... */}
func handleReceive_uiUpdateTimer(newDate: Date) { /* ... */}
}
I naively assumed the compiler directives were "invisible" and just presented the code seamlessly according to the switch. I have tried to create a ViewModifier to group them but failed to find a way to get the parameters (some with Bindings) and methods of the OSCommonView into a ViewModifier struct. At the moment I just duplicate the long list of view modifiers within each definition of body_watchOS and body_iOS.
If I put the modifiers inside the compiler switch above they work fine but that defeats the point of not duplicating them!
#if os(watchOS)
body_watchOS
.onAppear() { handleOnAppear() }
.onDisappear() { handleOnDisappear() }
...
#else
body_iOS
.onAppear() { handleOnAppear() }
.onDisappear() { handleOnDisappear() }
...
#endif
Any suggestions? Many thanks
答案1
得分: 1
You can wrap those kinds of directives in closures, while waiting for the missing feature that would negate the need for them:
var body: some View {
{
#if os(watchOS)
body_watchOS
#else
body_iOS
#endif
} ()
.onAppear(perform: handleOnAppear)
However, it's not obvious why you don't just do this:
var body: some View {
_body
.onAppear(perform: handleOnAppear)
#if os(watchOS)
private var _body: some View {
…
}
#else
private var _body: some View {
…
}
#endif
英文:
You can wrap those kinds of directives in closures, while waiting for the missing feature that would negate the need for them:
var body: some View {
{
#if os(watchOS)
body_watchOS
#else
body_iOS
#endif
} ()
.onAppear(perform: handleOnAppear)
However, it's not obvious why you don't just do this:
var body: some View {
_body
.onAppear(perform: handleOnAppear)
#if os(watchOS)
private var _body: some View {
…
}
#else
private var _body: some View {
…
}
#endif
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论