17

当我从 API 获取远程数据时,我使用 SwiftUI构建了一个LoadingView用于在我的应用程序中显示一些加载内容的工具。我使用的是 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.isLoadingLoadingView. 在这一行中,我收到以下错误:

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

我尝试了几种方法,但这些方法都不起作用。顺便说一句:如果我在其中使用一个@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("")
        }
    }
}

我错过了什么吗?如果您需要更多信息,请告诉我,如果需要,我可以提供更多内容。

谢谢您的帮助!

4

2 回答 2

14

由于您LoadingView不打算修改 .isLoading,因此您不需要将其作为绑定传递:

LoadingView(isShowing: self.$charStore.isLoading)

相反,删除@Bindingin LoadingView

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

    var isShowing: Bool
    ...

并像这样创建它(删除美元符号):

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

相反,如果您坚持传递绑定,则需要删除private(set)from:

@Published private(set) var isLoading = false
于 2019-08-09T06:13:24.073 回答
-1

您不能执行以下操作:

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

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 参数。

如果我错了,请纠正我!

于 2019-08-09T11:30:47.237 回答