我使用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("")
}
}
}
我想念东西吗?如果您需要更多信息,请告诉我,如果需要,我可以提供更多内容。
感谢您的帮助!
答案 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参数。
如果我错了,请纠正我!