gpt4 book ai didi

firebase - 如何使用获取的数据刷新 View - Firestore 和 SwiftUI

转载 作者:行者123 更新时间:2023-12-03 13:40:24 24 4
gpt4 key购买 nike

短:我认为的图像在第一次加载后没有更新。 URL 保持与之前加载的 View 相同,但是不从存储中获取 URL 或数据的 View 的其余部分被更新。
完整:我有两个 View ,一个 ListView和一个 DetailView .
ListView表示List型一览.详细 View 应该显示每个 Profile来自 List.profiles .我通过存储每个字符串来做到这一点 uidList.profiles并调用 model.fetchProfiles获取每个选定列表的配置文件。
上第一选List model.fetchProfiles返回文档和 model.profilesDetailView 中显示数据很好.
第一次加载 DetailViewProfileRow出现时被调用并记录获取的配置文件。然后是ProfileRow加载 imageURL来自 imagePath并使用它来获取图像。
控制台:加载列表 1

CARD DID APPEAR: Profiles []
CARD DID APPEAR: SortedProfiles []CARD ROW
CARD ROW DID APPEAR: Profiles profiles/XXXXXX/Profile/profile.png
CARD ROW DID APPEAR: SortedProfiles profiles/XXXXXX/Profile/profile.png
Get url from image path: profiles/XXXXXX/Profile/profile.png
Image URL: https://firebasestorage.googleapis.com/APPNAME/profiles%XXXXXXX


选择第二个时 List来自 ListView ProfileRow didAppear不是因为;
if model.profiles.count > 0 {
print("CARD ROW DID APPEAR: Profiles \(model.profiles[0]. imgPath)")
print("CARD ROW DID APPEAR: Sorted \(model.sortedProfiles[0].imgPath)")
}
并且不会再选择 ListListView ,但是 ProfileRow 中的其余配置文件数据显示如名称,因此必须获取数据。 ImagePath与加载完全相同图像的第一个 View 相同。 Profile 的所有其他属性例如名称被正确加载。
控制台:加载列表2

CARD DID APPEAR: Profiles []
CARD DID APPEAR: SortedProfiles []CARD ROW
Get url from image path: profiles/XXXXXX/Profile/profile.pngImage URL:https://firebasestorage.googleapis.com/APPNAME/profiles%XXXXXXX


如果我然后导航到 List1然后是 List2 的图像出现,如果我重新选择 List2图像看起来不错。 The image show is correct on first load, and when selecting another list it always the one from before.
谁能帮我吗 ?
第一次查看
struct ListViw: View {
@EnvironmentObject var model: Model

var body: some View {
VStack {

ForEach(model.lists.indices, id: \.self) { index in
NavigationLink(
destination: DetailView()
.environmentObject(model)
.onAppear() {
model.fetchProfiles()
}
) {
ListRow(home:model.lists[index])
.environmentObject(model)
}
.isDetailLink(false)
}
}
}

}
详情查看卡
struct ProfilesCard: View {

@EnvironmentObject var model: Model

var body: some View {
VStack(alignment: .trailing, spacing: 16) {
if !model.sortedProfiles.isEmpty {
VStack(alignment: .leading, spacing: 16) {
ForEach(model.sortedProfiles.indices, id: \.self) { index in
ProfileRow(
name: "\(model.sortedProfiles[index].firstName) \(model.sortedProfiles[index].lastName)",
imgPath: model.sortedProfiles[index].imgPath,
index: index)
.environmentObject(model)
}
}
.padding(.top, 16)
}

}//End of Card
.modifier(Card())
.onAppear() {
print("CARD DID APPEAR: Profiles \(model.profiles)")
print("CARD DID APPEAR: SORTED \(model.sortedTenants)")
}
}
}



struct ProfileRow: View {

@EnvironmentObject var model: Model

@State var imageURL = URL(string: "")

var name: String
var imgPath: String
var index: Int

private func loadImage() {
print("load image: \(imgPath)")
DispatchQueue.main.async {
fm.getURLFromFirestore(path: imgPath, success: { (imgURL) in
print("Image URL: \(imgURL)")
imageURL = imgURL
}) { (error) in
print(error)
}
}
}

var body: some View {
VStack(alignment: .leading, spacing: 12) {
HStack(alignment: .center, spacing: 12) {

KFImage(imageURL,options: [.transition(.fade(0.2)), .forceRefresh])
.placeholder {
Rectangle().foregroundColor(.gray)
}
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 32, height: 32)
.cornerRadius(16)


// Profile text is always displayed correctly
Text(name)
.modifier(BodyText())
.frame(maxWidth: .infinity, alignment: .leading)
}
}
.onAppear() {
print("CARD ROW")

// Crashes if check is not there
if model.profiles.count > 0 {

print("CARD ROW DID APPEAR: Profiles \(model.profiles[0]. imgPath)")

print("CARD ROW DID APPEAR: Sorted \(model.sortedProfiles[0].imgPath)")
}

loadImage()
}
}
}
型号
class Model: ObservableObject {

init() {
fetchData()
}

@Published var profiles: [Profile] = []
var sortedProfiles: [Profile] {return profiles.removeDuplicates }

@Published var list: List? {
didSet {
fetchProfiles()
}
}

func fetchData() {
if let currentUser = Auth.auth().currentUser {

email = currentUser.email!

db.collection("lists")
.whereField("createdBy", isEqualTo: currentUser.uid)
.addSnapshotListener { (querySnapshot, error) in
guard let documents = querySnapshot?.documents else {
return
}

self.lists = documents.compactMap { queryDocumentSnapshot -> List? in
return try? queryDocumentSnapshot.data(as: List.self)
}
}

}
}

func fetchProfiles() {
profiles.removeAll()

for p in list!.profiles {
firestoreManager.fetchProfile(uid: t, completion: { [self] profile in
profiles.append(profile)
})
}
}

}
更新
到目前为止我尝试过的是使用 didSetImgPathImgURL但仍然不是运气。也曾尝试使用 model.profiles直接地。

最佳答案

在使用 Firestore API 的所有回调中,对主队列上的已发布或状态属性进行分配,因为回调可能会在后台队列上调用。
所以,假设数据被正确返回和解析,它应该是这样的

for p in list!.profiles {
firestoreManager.fetchProfile(uid: t, completion: { [self] profile in
DispatchQueue.main.async {
profiles.append(profile)
}
})
}
我还建议避免使用 SDK 类型为您的自定义类型命名 - 可能会出现非常令人困惑的非明显错误
// List model below might conflict with SwiftUI List
return try? queryDocumentSnapshot.data(as: List.self)

关于firebase - 如何使用获取的数据刷新 View - Firestore 和 SwiftUI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66162810/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com