SwiftUI中UIImage未传入Firebase上传函数的问题排查与修复
问题原因及修复方案
问题现象
从相机胶卷选择照片后能正常在界面展示,但点击「Save Photos」按钮上传至Firebase时,uploadAsJPEG/uploadAsJPEG1x1接收的是空UIImage数组。排查发现执行loadImages时图片能正常添加到数组,但传入ImageStorageService时数组为空。
核心原因
你创建了两个完全独立的OnboardingViewModel实例:
TestView中通过@StateObject private var viewModel = OnboardingViewModel()创建了一个实例,上传操作使用的是这个实例的images数组ImageSelectorView中又通过@ObservedObject private var viewModel = OnboardingViewModel()创建了另一个独立实例,选图添加图片的操作是在这个实例的images数组中完成的
两个实例的images数组完全隔离,上传时自然拿不到选中的图片。
修复步骤
1. 修改ImageSelectorView,接收外部传入的ViewModel
将ImageSelectorView内部的ViewModel实例移除,改为从外部传入:
struct ImageSelectorView: View { // 移除内部初始化,改为接收外部传入的viewModel @ObservedObject var viewModel: OnboardingViewModel var body: some View { NavigationView { VStack { ZStack { Rectangle() .fill(Color.secondary) Text("Tap To Select Photos") .foregroundColor(.white) .font(.headline) } .onTapGesture { viewModel.isShowingImagePicker = true } HStack { ForEach(viewModel.images.indices, id: \.self) { index in ImageView(uiImage: viewModel.images[index]) } } } .padding([.horizontal, .bottom]) .onChange(of: viewModel.inputImage) { _ in viewModel.loadImages() } .sheet(isPresented: $viewModel.isShowingImagePicker) { ImagePicker(image: $viewModel.inputImage) } } } }
2. 在TestView中传入共享的ViewModel
调用ImageSelectorView时,传入TestView自己的ViewModel实例:
struct TestView: View { @StateObject private var viewModel = OnboardingViewModel() @State private var isUploading = false var body: some View { VStack { // 传入共享的viewModel ImageSelectorView(viewModel: viewModel) Button(action: { Task { isUploading = true await viewModel.uploadAndUpdateImageURLs(email: "test@test.com", images: viewModel.images) isUploading = false } }, label: { Text("Save Photos") }) if isUploading { ProgressView() } } } }
3. 确保OnboardingViewModel符合ObservableObject协议
确认你的OnboardingViewModel类声明了ObservableObject(如果之前没加的话):
@MainActor class OnboardingViewModel: ObservableObject { @Published var images: [UIImage] = [] @Published var inputImage: UIImage? @Published var isShowingImagePicker = false // 补充视图用到的属性 // 原有方法保持不变 func uploadAndUpdateImageURLs(email: String, images: [UIImage]) async { print("uploadAndUpdateImageURLs Reached") do { let imageURLs = try await ImageStorageService.uploadAsJPEG(images: images, path: "users") print("ImageURLs is currently: \(imageURLs)") print("Count of imageURLs is: \(imageURLs.count)") for imageURL in imageURLs { await updateImageURLs(email: email, imageURL: imageURL.absoluteString) } } catch { print("error uploading and updating imageURLs: \(error.localizedDescription)") } } func loadImages() { guard let inputImage = inputImage else { return } images.append(inputImage) print("images array is currently \(images)") } }
这样修改后,选图和上传操作会共享同一个ViewModel实例,images数组的内容就能同步传递到上传方法中了。
内容的提问来源于stack exchange,提问作者Donald Dang
相关产品推荐
相关产品推荐

