SwiftUI:无法推断通用参数“主题”

时间:2019-08-09 05:55:26

标签: swift swiftui swift5 combine

我使用SwiftUI构建了LoadingView,用于在我从API提取远程数据时在我的应用程序中显示一些加载内容。我正在使用Xcode 11.0 beta 5。

这是LoadingView

struct LoadingView<Content>: View where Content: View {

    @Binding var isShowing: Bool
    var content: () -> Content

    var body: some View {

        GeometryReader { geometry in

            ZStack(alignment: .center) {

                self.content()
                    .disabled(self.isShowing)
                    .blur(radius: self.isShowing ? 3 : 0)

                VStack {
                    Text("Loading...")
                    ActivityIndicator(isAnimating: .constant(true), style: .large)
                }
                .frame(width: geometry.size.width / 2,
                       height: geometry.size.height / 5)
                    .background(Color.white)
                    .foregroundColor(Color.primary)
                    .cornerRadius(5)
                    .opacity(self.isShowing ? 1 : 0)
            }
        }
    }
}

这是我的数据存储。它被声明为ObservableObject,并且具有多个@Published属性。此外,它还可以通过API进行一些远程获取:

class CharacterStore: ObservableObject {

    @Published private(set) var isLoading = false


    // Fetches some stuff from a remote api
    func fetch() {

        self.isLoading = true

        myService.getCharacters { (result) in
            DispatchQueue.main.async {
                self.isLoading = false
            }
        }
    }
}

最后,这是我要显示其LoadingView内容的ContentView视图。当然,我需要在显示此视图之前设置@EnvironmentObject

struct ContentView: View {

    @EnvironmentObject var charStore: CharacterStore

    var body: some View {

        LoadingView(isShowing: self.$charStore.isLoading) { // Here I get the error

            // Show some Content here
            Text("")
        }
    }
}

问题是我想将self.$charStore.isLoading绑定到LoadingView。在这一行中,我得到以下错误:

  

无法推断出通用参数'Subject'

我尝试了几种方法,但是这些都不起作用。顺便说一句:如果我在@State中使用ContentView属性,它就可以像这样正常工作:

struct ContentView: View {

    @EnvironmentObject var charStore: CharacterStore

    @State var loads: Bool = false

    var body: some View {

        LoadingView(isShowing: self.$loads) { // Here I get no error

            // Show some Content here
            Text("")
        }
    }
}

我想念东西吗?如果您需要更多信息,请告诉我,如果需要,我可以提供更多内容。

感谢您的帮助!

2 个答案:

答案 0 :(得分:5)

由于您的LoadingView不会修改.isLoading,因此您无需将其作为绑定传递:

LoadingView(isShowing: self.$charStore.isLoading)

相反,请删除@Binding中的LoadingView

struct LoadingView<Content>: View where Content: View {

    var isShowing: Bool
    ...

并像这样创建它(去掉美元符号):

LoadingView(isShowing: self.charStore.isLoading) { ... }

相反,如果您坚持要传递绑定,则需要从以下位置删除private(set)

@Published private(set) var isLoading = false

答案 1 :(得分:0)

您不能执行以下操作:

用与ContentView相同的@EnvironmentObject替换@Binding。

struct LoadingView<Content>: View where Content: View {
    @EnvirontmentObject var charStore: CharacterStore // added
    //@Binding var isShowing: Bool // removed
    var content: () -> Content

    var body: some View {

        GeometryReader { geometry in

            ZStack(alignment: .center) {

                self.content()
                    .disabled(self.$charStore.isLoading) // Changed
                    .blur(radius: self.$charStore.isLoading ? 3 : 0) // Changed

                VStack {
                    Text("Loading...")
                    ActivityIndicator(isAnimating: .constant(true), style: .large)
                }
                .frame(width: geometry.size.width / 2,
                       height: geometry.size.height / 5)
                    .background(Color.white)
                    .foregroundColor(Color.primary)
                    .cornerRadius(5)
                    .opacity(self.$charStore.isLoading ? 1 : 0) // Changed
            }
        }
    }
}

当然,您还必须从ContentView的LoadingView()初始化程序中删除isShowing参数。

如果我错了,请纠正我!