数组更改时 SwiftUI 列表不更新
SwiftUI list not updating when the array changes
VStack(spacing: 0){
List{
ForEach(postsData.fetchedPosts, id: \.postID) { post in
SocialPostView(post: post, showAccount: self.$showAccount, fetchedUser: self.$fetchedUser)
.padding(.vertical)
.listRowInsets(EdgeInsets())
.onAppear {
self.elementOnAppear(post)
}
}
}
.pullToRefresh(isShowing: $isShowing) {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.isShowing = false
self.postsData.newFetch = true
self.postsData.fetchPosts(userInfo: self.userInfo)
}
}
}
private func elementOnAppear(_ post: Post) {
/* onAppear on the view is called when a view appears on screen.
elementOnAppear asks the view model if the element is the last one.
If so, we ask the view model to fetch new data. */
if self.postsData.isLastPostInList(post: post) {
self.postsData.fetchPosts(userInfo: self.userInfo)
}
}
当每个列表元素出现时,它会检查它是否是数组中的最后一个元素。如果是,它会从 Firestore 获取更多信息并更新 fetchedPosts
。但是,当数组更新时,列表没有更新,所以没有新元素出现。
这是发布数组的 ObservableObject。
class SocialObservable: ObservableObject{
let db = Firestore.firestore()
let objectWillChange = ObservableObjectPublisher()
@Published var fetchedPosts = [Post]()
@Published var lastSnap : DocumentSnapshot?
@Published var reachedEnd = false
var currentListener: ListenerRegistration?
var newFetch = false {
willSet{
objectWillChange.send()
}
}
init(userInfo: UserData){
print(userInfo.uid)
fetchPosts(userInfo: userInfo)
}
func fetchPosts(userInfo: UserData){
var first: Query?
if lastSnap == nil || newFetch {
//not last snapshot, or just updated feed
if newFetch{
newFetch.toggle()
fetchedPosts = [] // clean up if new fetch
}
first = db.collection("posts")
.whereField("availability", arrayContains: userInfo.uid)
.order(by: "date", descending: true)
.limit(to: 1)
}
else {
first = db.collection("posts")
.whereField("availability", arrayContains: userInfo.uid)
.order(by: "date", descending: true)
.start(afterDocument: lastSnap!)
.limit(to: 1)
}
first?.getDocuments(completion: { (snapshot, error) in
guard let snapshot = snapshot else {
print("Error: \(error.debugDescription)")
return
}
let doc = snapshot.documents.map({postFromDB(obj: [=12=].data(), id: [=12=].documentID)})
doc.map({print([=12=].postID)})
// append to fetched posts
self.fetchedPosts = self.fetchedPosts + doc
print(self.fetchedPosts.count)
//prepare for the next fetch
guard let lastSnapshot = snapshot.documents.last else {
// the collection is empty. no data fetched
self.reachedEnd = true
return
}
// save last snapshot
self.lastSnap = lastSnapshot
})
}
func isLastPostInList(post: Post) -> Bool {
return post.postID == fetchedPosts.last?.postID
}
}
有什么解决方法吗?
几件事
class SocialObservable: ObservableObject{
let db = Firestore.firestore()
// let objectWillChange = ObservableObjectPublisher() // << remove this
// ...
var newFetch = false {
willSet{
self.objectWillChange.send() // ObservableObject has default
}
}
// ...
并在主队列上发布更新修改
doc.map({print([=11=].postID)})
// append to fetched posts
DispatchQueue.main.async {
self.fetchedPosts = self.fetchedPosts + doc
}
print(self.fetchedPosts.count)
VStack(spacing: 0){
List{
ForEach(postsData.fetchedPosts, id: \.postID) { post in
SocialPostView(post: post, showAccount: self.$showAccount, fetchedUser: self.$fetchedUser)
.padding(.vertical)
.listRowInsets(EdgeInsets())
.onAppear {
self.elementOnAppear(post)
}
}
}
.pullToRefresh(isShowing: $isShowing) {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.isShowing = false
self.postsData.newFetch = true
self.postsData.fetchPosts(userInfo: self.userInfo)
}
}
}
private func elementOnAppear(_ post: Post) {
/* onAppear on the view is called when a view appears on screen.
elementOnAppear asks the view model if the element is the last one.
If so, we ask the view model to fetch new data. */
if self.postsData.isLastPostInList(post: post) {
self.postsData.fetchPosts(userInfo: self.userInfo)
}
}
当每个列表元素出现时,它会检查它是否是数组中的最后一个元素。如果是,它会从 Firestore 获取更多信息并更新 fetchedPosts
。但是,当数组更新时,列表没有更新,所以没有新元素出现。
这是发布数组的 ObservableObject。
class SocialObservable: ObservableObject{
let db = Firestore.firestore()
let objectWillChange = ObservableObjectPublisher()
@Published var fetchedPosts = [Post]()
@Published var lastSnap : DocumentSnapshot?
@Published var reachedEnd = false
var currentListener: ListenerRegistration?
var newFetch = false {
willSet{
objectWillChange.send()
}
}
init(userInfo: UserData){
print(userInfo.uid)
fetchPosts(userInfo: userInfo)
}
func fetchPosts(userInfo: UserData){
var first: Query?
if lastSnap == nil || newFetch {
//not last snapshot, or just updated feed
if newFetch{
newFetch.toggle()
fetchedPosts = [] // clean up if new fetch
}
first = db.collection("posts")
.whereField("availability", arrayContains: userInfo.uid)
.order(by: "date", descending: true)
.limit(to: 1)
}
else {
first = db.collection("posts")
.whereField("availability", arrayContains: userInfo.uid)
.order(by: "date", descending: true)
.start(afterDocument: lastSnap!)
.limit(to: 1)
}
first?.getDocuments(completion: { (snapshot, error) in
guard let snapshot = snapshot else {
print("Error: \(error.debugDescription)")
return
}
let doc = snapshot.documents.map({postFromDB(obj: [=12=].data(), id: [=12=].documentID)})
doc.map({print([=12=].postID)})
// append to fetched posts
self.fetchedPosts = self.fetchedPosts + doc
print(self.fetchedPosts.count)
//prepare for the next fetch
guard let lastSnapshot = snapshot.documents.last else {
// the collection is empty. no data fetched
self.reachedEnd = true
return
}
// save last snapshot
self.lastSnap = lastSnapshot
})
}
func isLastPostInList(post: Post) -> Bool {
return post.postID == fetchedPosts.last?.postID
}
}
有什么解决方法吗?
几件事
class SocialObservable: ObservableObject{
let db = Firestore.firestore()
// let objectWillChange = ObservableObjectPublisher() // << remove this
// ...
var newFetch = false {
willSet{
self.objectWillChange.send() // ObservableObject has default
}
}
// ...
并在主队列上发布更新修改
doc.map({print([=11=].postID)})
// append to fetched posts
DispatchQueue.main.async {
self.fetchedPosts = self.fetchedPosts + doc
}
print(self.fetchedPosts.count)