SwiftUI中如何通过PhotosUI调用类WhatsApp的图片裁剪界面?
实现类似WhatsApp的图片裁剪界面
你提到的裁剪界面确实是Apple提供的系统原生图片编辑UI,并非WhatsApp自定义。在SwiftUI中可以通过两种方式调用,具体实现如下:
方式一:基于UIImagePickerController(UIKit包装)
这是传统实现方式,通过UIViewControllerRepresentable将UIKit的UIImagePickerController包装为SwiftUI组件,开启编辑模式即可调出裁剪界面:
import SwiftUI import UIKit struct ImagePicker: UIViewControllerRepresentable { @Binding var selectedImage: UIImage? @Binding var isPresented: Bool func makeUIViewController(context: Context) -> UIImagePickerController { let picker = UIImagePickerController() picker.sourceType = .photoLibrary picker.delegate = context.coordinator picker.allowsEditing = true // 开启原生编辑/裁剪模式 return picker } func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {} func makeCoordinator() -> Coordinator { Coordinator(self) } class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate { let parent: ImagePicker init(_ parent: ImagePicker) { self.parent = parent } func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { // 优先获取裁剪后的图片,无则返回原图 parent.selectedImage = info[.editedImage] as? UIImage ?? info[.originalImage] as? UIImage parent.isPresented = false } func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { parent.isPresented = false } } } // 使用示例 struct ContentView: View { @State private var selectedImage: UIImage? @State private var showPicker = false var body: some View { VStack { if let image = selectedImage { Image(uiImage: image) .resizable() .scaledToFit() } Button("选择图片") { showPicker = true } } .sheet(isPresented: $showPicker) { ImagePicker(selectedImage: $selectedImage, isPresented: $showPicker) } } }
方式二:PHPicker(PhotosUI框架)+ 系统图片编辑控制器
如果偏好使用iOS 14+推出的PhotosUI框架PHPicker,可以在选中图片后调用系统的UIImageViewController打开编辑界面:
import SwiftUI import PhotosUI import UIKit struct PhotoPicker: UIViewControllerRepresentable { @Binding var selectedImage: UIImage? @Binding var isPresented: Bool func makeUIViewController(context: Context) -> PHPickerViewController { var configuration = PHPickerConfiguration() configuration.filter = .images configuration.selectionLimit = 1 let picker = PHPickerViewController(configuration: configuration) picker.delegate = context.coordinator return picker } func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) {} func makeCoordinator() -> Coordinator { Coordinator(self) } class Coordinator: NSObject, PHPickerViewControllerDelegate { let parent: PhotoPicker init(_ parent: PhotoPicker) { self.parent = parent } func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) { picker.dismiss(animated: true) guard let result = results.first, result.itemProvider.canLoadObject(ofClass: UIImage.self) else { parent.isPresented = false return } result.itemProvider.loadObject(ofClass: UIImage.self) { [weak self] image, error in guard let self = self, let image = image as? UIImage else { return } DispatchQueue.main.async { // 初始化系统图片编辑控制器 let editController = UIImageViewController() editController.image = image editController.delegate = self // 获取当前窗口并present编辑界面 if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, let window = windowScene.windows.first { window.rootViewController?.present(editController, animated: true) } } } } } } // 扩展Coordinator实现编辑回调 extension PhotoPicker.Coordinator: UIImageViewControllerDelegate { func imageViewController(_ imageViewController: UIImageViewController, didFinishEditingWith image: UIImage?, editingInfo: [UIImageViewController.InfoKey : Any]?) { parent.selectedImage = image imageViewController.dismiss(animated: true) { parent.isPresented = false } } } // 使用示例 struct ContentView: View { @State private var selectedImage: UIImage? @State private var showPicker = false var body: some View { VStack { if let image = selectedImage { Image(uiImage: image) .resizable() .scaledToFit() } Button("选择图片") { showPicker = true } } .sheet(isPresented: $showPicker) { PhotoPicker(selectedImage: $selectedImage, isPresented: $showPicker) } } }
关键注意事项
- 方式一的
UIImagePickerController默认提供正方形裁剪,和WhatsApp的基础裁剪体验完全一致; - 方式二的
UIImageViewController支持更多编辑选项(调整比例、旋转、滤镜等),用户可手动切换到正方形裁剪模式; - 两种方式均使用Apple原生组件,无需自定义UI;
- 必须在
Info.plist中添加NSPhotoLibraryUsageDescription权限描述,否则会触发崩溃。
内容的提问来源于stack exchange,提问作者rayaantaneja
相关产品推荐
相关产品推荐

