仅在Aync用完成处理程序解析后更新视图



我试图更新我的视图,只有在Async调用被解决后。在下面的代码中,arrayOfTodos.itemsTodoListApp被渲染后不久异步进入。我遇到的问题是,当onAppear运行时,self.asyncTodoList.items总是空,因为它还没有从网络调用收到数组的值。我被困在试图找出如何推迟运行onAppear,直到承诺解决后,像一个完成处理程序?并根据网络调用的结果,再修改视图。谢谢你的帮助!我被困在这上面的时间比我承认的还要长!

struct ContentView: View {

@StateObject var arrayOfTodos = AsyncGetTodosNetworkCall()

var body: some View {
TodoListApp(asyncTodoList: arrayOfTodos)
}
}
struct TodoListApp: View {

@ObservedObject var asyncTodoList: AsyncGetTodosNetworkCall
@State private var showPopUp: Bool = false

var body: some View {
NavigationView {

ZStack {

VStack {

Text("Top Area")
Text("List Area")

}

if self.showPopUp == true {
VStack {
Text("THIS IS MY POPUP!")
Text("No Items Added Yet")
}.frame(width: 300, height: 400)
}

}.onAppear {
let arrayItems = self.asyncTodoList
if arrayItems.items.isEmpty {
self.showPopUp = true
}

/*HERE! arrayItems.items.isEmpty is ALWAYS empty when onAppear 
runs since it's asynchronous.  What I'm trying to do is only
show the popup if the array is empty after the promise is
resolved.
What is happening is even if array resolved with multiple todos,
the popup is still showing because it was initially empty on
first run. */

}

}
}
}
class AsyncGetTodosNetworkCall: ObservableObject {

@AppStorage(DBUser.userID) var currentUserId: String?
private var REF_USERS = DB_BASE.collection(DBCOLLECTION.appUsers)
@Published var items = [TodoItem]()

func fetchTodos(toDetach: Bool) {

guard let userID = currentUserId else {
return
}

let userDoc = REF_USERS.document(String(userID))
.collection(DBCOLLECTION.todos)
.addSnapshotListener({ (querySnapshot, error) in

guard let documents = querySnapshot?.documents else {
print("No Documents Found")
return
}

self.items = documents.map { document -> TodoItem in

let todoID = document.documentID
let todoName = document.get(ToDo.todoName) as? String ?? ""
let todoCompleted = document.get(Todo.todoCompleted) as? Bool ?? false

return TodoItem(
id: todoID,
todoName: todoName,
todoCompleted: todoCompleted
)
}
})
if toDetach == true {
userDoc.remove()
}
}
}

在准备问题的时候,我找到了自己的答案。这里是以防将来有人可能遇到同样的问题。

struct ContentView: View {
@StateObject var arrayOfTodos = AsyncGetTodosNetworkCall()

@State var hasNoTodos: Bool = false
func getData() {
self.arrayOfTodos.fetchTodos(toDetach: false) { noTodos in

if noTodos {
self.hasNoTodos = true
}
}
}
func removeListeners() {
self.arrayOfTodos.fetchTodos(toDetach: true)
}
var body: some View {
TabView {
TodoListApp(asyncTodoList: arrayOfTodos, hasNoTodos : self.$hasNoTodos)
}.onAppear(perform: {
self.getData()
}).onDisappear(perform: {
self.removeListeners()
})
}
}
struct TodoListApp: View {
@ObservedObject var asyncTodoList: AsyncGetTodosNetworkCall
@Binding var hasNoTodos: Bool
@State private var hidePopUp: Bool = false
var body: some View {
NavigationView {
ZStack {
VStack {
Text("Top Area")

ScrollView {
LazyVStack {

ForEach(asyncTodoList.items) { item in

HStack {
Text("(item.name)")
Spacer()
Text("Value")
}

}
}
}
}

if self.hasNoTodos == true {
if self.hidePopUp == false {

VStack {
Text("THIS IS MY POPUP!")
Text("No Items Added Yet")
}.frame(width: 300, height: 400)

}
}
}
}
}
}
class AsyncGetTodosNetworkCall: ObservableObject {
@AppStorage(DBUser.userID) var currentUserId: String?
private var REF_USERS = DB_BASE.collection(DBCOLLECTION.appUsers)
@Published var items = [TodoItem]()
func fetchTodos(toDetach: Bool, handler: @escaping (_ noTodos: Bool) -> ()) {
guard let userID = currentUserId else {
handler(true)
return
}
let userDoc = REF_USERS.document(String(userID))
.collection(DBCOLLECTION.todos)
.addSnapshotListener({ (querySnapshot, error) in
guard let documents = querySnapshot?.documents else {
print("No Documents Found")
handler(true)
return
}
self.items = documents.map { document -> TodoItem in
let todoID = document.documentID
let todoName = document.get(ToDo.todoName) as? String ?? ""
let todoCompleted = document.get(Todo.todoCompleted) as? Bool ?? false
return TodoItem(
id: todoID,
todoName: todoName,
todoCompleted: todoCompleted
)
}
handler(false)
})
if toDetach == true {
userDoc.remove()
}
}
}

最新更新