You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 07:16:10