SwiftUI中如何将ImagePicker选中的图片传递到其他视图?
解决图库选图无法绑定到UploadPostView的问题
你当前的问题出在两个核心点:
- 从图库选图后,
ImagePicker的uiImage没有同步到capturedImage绑定变量,导致UploadPostView无法获取到图库选择的图片 UploadPostView内部新建了独立的ImagePicker实例,和CustomCameraView里的不是同一个,自然拿不到选图结果
以下是具体修复步骤:
第一步:修改CustomCameraView,同步图库选图到capturedImage
在CustomCameraView中添加对imagePicker.$uiImage的监听,当图库选图完成后自动更新capturedImage:
import SwiftUI import PhotosUI struct CustomCameraView: View { let cameraService = CameraService() @Environment(\.dismiss) private var dismiss @StateObject var imagePicker = ImagePicker() @Binding var capturedImage: UIImage? var body: some View { // 照片已拍摄或已选择时进入编辑页 if (imagePicker.image != nil) || (capturedImage != nil) { UploadPostView(capturedImage: $capturedImage) } // 未选择/拍摄照片时显示相机界面 else { ZStack (alignment: .topLeading) { CameraView(cameraService: cameraService) { result in switch result { case .success(let photo): if let data = photo.fileDataRepresentation() { capturedImage = UIImage(data: data) } else { print("Error: no image data found") } case .failure(let err): print(err.localizedDescription) } } VStack (alignment: .leading) { Button { dismiss() } label: { Image("xmark") .renderingMode(.template) .resizable() .frame(width: 28, height: 28) .foregroundColor(.white) } .padding() Spacer() HStack { PhotosPicker(selection: $imagePicker.imageSelection) { Image("image-square") .renderingMode(.template) .resizable() .frame(width: 32, height: 28) .foregroundColor(.white) } Spacer() Button { cameraService.capturePhoto() } label: { Image(systemName: "circle") .font(.system(size: 72)) .foregroundColor(.white) } Spacer() Rectangle() .foregroundColor(.clear) .frame(width: 32, height: 28) } .padding() } } .cornerRadius(6) .background(.black) // 新增监听:图库选图完成后同步到capturedImage .onChange(of: imagePicker.uiImage) { newImage in if let newImage = newImage { capturedImage = newImage } } } } }
第二步:简化UploadPostView,移除冗余的ImagePicker
UploadPostView不需要单独创建ImagePicker,直接使用绑定的capturedImage即可,统一图片显示和上传逻辑:
import SwiftUI import Kingfisher import PhotosUI struct UploadPostView: View { @Environment(\.dismiss) private var dismiss @ObservedObject var viewModel = UploadPostViewModel() @State var caption = "" @State var rating = 0 @Binding var capturedImage: UIImage? var body: some View { VStack { // 统一显示capturedImage(拍摄或图库选择的图片) if let image = capturedImage { Image(uiImage: image) .resizable() .aspectRatio(contentMode: .fill) .frame(minWidth: 100, maxWidth: .infinity, minHeight: 100, maxHeight: .infinity) .cornerRadius(6) .clipped() } HStack { Spacer() Button { if let uiimage = capturedImage { viewModel.uploadPost(caption: caption, image: uiimage, rating: rating) viewModel.loading = true } } label: { if viewModel.loading { ProgressView() .progressViewStyle(CircularProgressViewStyle(tint: .white)) .frame(width: 24, height: 24) .padding() .background(Color.accentColor) .foregroundColor(.white) .clipShape(Circle()) } else { Image("send-fill") .renderingMode(.template) .resizable() .frame(width: 24, height: 24) .padding() .background(Color.accentColor) .foregroundColor(.white) .clipShape(Circle()) } } }.padding(8) } .background(.black) .onReceive(viewModel.$didUploadPost) { success in if success { dismiss() } } } }
可选优化:让ImagePicker直接支持外部绑定(更内聚的写法)
如果后续需要复用ImagePicker,可以修改它直接接收外部绑定变量,省去额外的监听逻辑:
import SwiftUI import PhotosUI @MainActor class ImagePicker: ObservableObject { @Published var image: Image? @Published var uiImage: UIImage? // 新增外部绑定变量 @Binding var externalImage: UIImage? // 修改初始化方法,接收绑定参数 init(externalImage: Binding<UIImage?>) { self._externalImage = externalImage } @Published var imageSelection: PhotosPickerItem? { didSet { if let imageSelection { Task { try await loadTransferable(from: imageSelection) } } } } func loadTransferable(from imageSelection: PhotosPickerItem?) async throws { do { if let data = try await imageSelection?.loadTransferable(type: Data.self) { if let uiImage = UIImage(data: data) { self.uiImage = uiImage self.image = Image(uiImage: uiImage) // 直接同步到外部绑定变量 self.externalImage = uiImage } } } catch { print(error.localizedDescription) image = nil externalImage = nil } } }
使用时,在CustomCameraView中初始化ImagePicker:
struct CustomCameraView: View { let cameraService = CameraService() @Environment(\.dismiss) private var dismiss @StateObject var imagePicker: ImagePicker @Binding var capturedImage: UIImage? // 自定义初始化方法 init(capturedImage: Binding<UIImage?>) { self._capturedImage = capturedImage self._imagePicker = StateObject(wrappedValue: ImagePicker(externalImage: capturedImage)) } // ... 其余代码保持不变,可移除之前添加的onChange监听 }
内容的提问来源于stack exchange,提问作者amelia
相关产品推荐
相关产品推荐

