Ril*_*Dev 7 firebase google-cloud-firestore swiftui combine
简短:我认为的图像在第一次加载后没有更新。URL 保持与之前加载的视图相同,但是不从存储中获取 URL 或数据的视图的其余部分被更新。
完整:我有两个视图, aListView
和 a DetailView
。
在ListView
I 中显示一个类型列表List
。详细视图应该显示每个Profile
来自List.profiles
. 为此,我将每个字符串存储uid
在其中List.profiles
并调用model.fetchProfiles
以获取所选每个列表的配置文件。
在第一个选择List
model.fetchProfiles
返回文档并model.profiles
在DetailView
.
当第一次装载DetailView
了ProfileRow
上出现被称为并记录配置文件获取。然后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
从图片获取网址路径:profiles/XXXXXX/Profile/profile.png
图片网址: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)")
}
Run Code Online (Sandbox Code Playgroud)
并且在选择List
in时不会再次出现ListView
,但是显示了 中的其余配置文件数据,ProfileRow
例如名称,因此必须获取数据。
这ImagePath
与加载完全相同图像的第一个视图相同。Profile
名称等的所有其他属性均已正确加载。
控制台:加载列表2
CARD DID APPEAR: Profiles []
CARD DID APPEAR: SortedProfiles [] CARD ROW
从图片路径获取网址:profiles/XXXXXX/Profile/profile.png 图片网址: 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)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
DetailView卡片
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()
}
}
}
Run Code Online (Sandbox Code Playgroud)
模型
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)
})
}
}
}
Run Code Online (Sandbox Code Playgroud)
更新
到目前为止,我尝试过的是didSet
用于ImgPath
或ImgURL
但仍然不是运气。也试过model.profiles
直接使用。
在使用 Firestore API 的所有回调中,为主队列上的已发布或状态属性进行分配,因为可能会在后台队列上调用回调。
因此,假设数据被正确返回并解析,这里应该是这样的
for p in list!.profiles {
firestoreManager.fetchProfile(uid: t, completion: { [self] profile in
DispatchQueue.main.async {
profiles.append(profile)
}
})
}
Run Code Online (Sandbox Code Playgroud)
另外,我建议避免使用 SDK 类型对自定义类型进行相同的命名 - 可能会出现非常令人困惑的非明显错误
// List model below might conflict with SwiftUI List
return try? queryDocumentSnapshot.data(as: List.self)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
313 次 |
最近记录: |