【发布时间】:2021-07-28 06:31:03
【问题描述】:
我将本教程用作参考。 https://www.raywenderlich.com/11609977-getting-started-with-cloud-firestore-and-swiftui
我基本上是在本教程中尝试将图像添加到卡片类型。
在我的应用中,AddStoryView 从用户输入中获取 2 个字符串 title & storyText 和一个 UIImage。
试图弄清楚当图像被编辑时如何更新ForEach 中的视图。
在我的模型中,我不知道如何将 UIImage 与 Codable 一起使用。所以,我尝试了另一种单独上传图片的方法。并使用获取StoryCardView 中故事图像的方法调用onAppear。它确实有效,但是在更新图像时它不会更新,直到应用重新启动。
import Foundation
import FirebaseFirestoreSwift
struct Story: Identifiable, Codable {
@DocumentID var id: String?
var author: String?
var headline :String?
var bodyText: String?
var userId: String?
var storyId: String?
// var storyImage: UIImage = UIImage(named: "logo")!
var comment: String?
}
这是StoriesListView 观察storyViewModels 以呈现故事的ViewModel:
import Foundation
import Combine
import PhotosUI
class StoryListViewModel: ObservableObject {
@Published var storyRepository = StoryRepository()
@Published var storyViewModels: [StoryViewModel] = []
private var cancellables: Set<AnyCancellable> = []
init() {
storyRepository.$stories.map { stories in
stories.map(StoryViewModel.init)
}
.assign(to: \.storyViewModels, on: self)
.store(in: &cancellables)
}
func addStory(story: Story, image: UIImage) {
storyRepository.uploadStory(story: story, image: image)
}
}
这里是StoryViewModel:
import Foundation
import Combine
class StoryViewModel: ObservableObject, Identifiable {
private let storyRepository = StoryRepository()
@Published var story: Story
private var cancellables: Set<AnyCancellable> = []
var id = ""
init(story: Story) {
self.story = story
// set up binding for story between the stories id and the viewmodels id then store object in cancellables so it can be canceled later
$story
.compactMap { $0.id }
.assign(to: \.id, on: self)
.store(in: &cancellables)
}
func editStory(story: Story, image: UIImage) {
storyRepository.updateStory(story, image)
}
}
这是使用 Firebase 处理通信的 Story Repository:
import FirebaseFirestore
import FirebaseFirestoreSwift
import FirebaseStorage
import Combine
import PhotosUI
class StoryRepository: ObservableObject {
////
private let path: String = "stories"
private let store = Firestore.firestore()
@Published var stories: [Story] = []
var userId = ""
private let authenticationService = AuthService()
private var cancellables: Set<AnyCancellable> = []
init() {
authenticationService.$user
.compactMap { user in
user?.uid
}
.assign(to: \.userId, on: self)
.store(in: &cancellables)
authenticationService.$user
.receive(on: DispatchQueue.main)
.sink { [weak self] _ in
self?.get()
}
.store(in: &cancellables)
}
func get(){
store.collection(path)
.addSnapshotListener{ querySnapshot, error in
if let error = error {
print("Error getting stories: \(error.localizedDescription)")
return
}
let stories = querySnapshot?.documents.compactMap {document in
try? document.data(as: Story.self)
} ?? []
DispatchQueue.main.async {
self.stories = stories
}
}
}
}
这里是StoriesListVIew:
struct StoriesListView: View {
@EnvironmentObject var storyListVM: StoryListViewModel
var body: some View {
ScrollView {
VStack (spacing: 20){
ForEach(storyListVM.storyViewModels) { storyViewModel in
StoryCardView(storyViewModel: storyViewModel)
}
}
.padding()
}
}
}
这里是整个故事在StoryRepository 中更新的地方:
func updateStory(_ story: Story, _ image: UIImage) {
guard let storyDocId = story.id else { return }
ImageManager.instance.uploadStoryImage(storyID: story.storyId ?? "", image: image) { (_ success: Bool) in
if success {
do {
try self.store.collection(self.path).document(storyDocId).setData(from: story)
} catch {
fatalError("Unable to add card: \(error.localizedDescription).")
}
return
} else {
print("Error uploading post image to firebase")
return
}
}
}
这就是我使用onAppear 在 StoryCardView 中显示图像的方式:
private func getStoryImage() {
ImageManager.instance.downloadStoryImage(storyID: storyViewModel.story.storyId ?? "") { (returnedImage) in
if let image = returnedImage {
DispatchQueue.main.async {
self.storyImg = image
}
}
}
}
【问题讨论】:
-
通过阅读您的问题,我很难弄清楚问题所在。你问怎么上传图片?或者试图弄清楚如何更新视图?但是,你没有
StoryCardView显示... 一般建议:ObservableObjects 的@Published数组将不起作用 --@Published适用于值类型,而不是引用类型。此外,在上传图像方面,您不应尝试将UIImage编码为 Codable 对象并存储它。存储文件的路径(例如String)并将文件与模型记录分开上传到 Firebase 存储。 -
我有图像 只是想在图像被编辑时如何更新列表中的视图。如果您查看教程,我只想将图像添加到他们的卡片中。感谢您的关注。
-
你的代码在哪里显示正在编辑的图像?
-
我会将该代码添加到问题中
-
所以您想在调用
updateStory时更新您的用户界面?但是您似乎没有在本地更新任何东西——它只是在更新 Firebase。您希望在当地看到什么变化?
标签: ios xcode firebase swiftui