05.如何在SwiftUI中使用ImagePicker?

一:问题

二:SwiftUIImagePicker

struct SwiftUIImagePicker {
    @Environment(\.presentationMode) var presentationMode
    @Binding var image: UIImage?
}

extension SwiftUIImagePicker: UIViewControllerRepresentable {
    func makeUIViewController(context: Context) -> some UIViewController {
        let picker = UIImagePickerController()
                return picker
    }

    func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {

    }
}

2.1 UIViewControllerRepresentable

这里使用了UIViewControllerRepresentable,我们的SwiftUIImagePicker就已经是一个标准的SwiftUIView了。

当创建一个SwiftUIImagePicker,SwiftUI会自动调用makeUIViewController()并返回一个UIImagePickerController.

2.2 Coordinator 代理中间件

由于SwiftUIImagePicker作为一个SwiftUI的View依旧不能使用NSObjectProtocol,所以我们需要一个中间件来完成代理。

UIViewControllerRepresentable中贴心的提供了这样一个中间件的定义,我们只要提供实现即可~

/// A type to coordinate with the view controller.
    associatedtype Coordinator = Void

    /// Creates the custom instance that you use to communicate changes from
    /// your view controller to other parts of your SwiftUI interface.
    ///
    /// Implement this method if changes to your view controller might affect
    /// other parts of your app. In your implementation, create a custom Swift
    /// instance that can communicate with other parts of your interface. For
    /// example, you might provide an instance that binds its variables to
    /// SwiftUI properties, causing the two to remain synchronized. If your view
    /// controller doesn't interact with other parts of your app, providing a
    /// coordinator is unnecessary.
    ///
    /// SwiftUI calls this method before calling the
    /// ``UIViewControllerRepresentable/makeUIViewController(context:)`` method.
    /// The system provides your coordinator either directly or as part of a
    /// context structure when calling the other methods of your representable
    /// instance.
    func makeCoordinator() -> Self.Coordinator

我们来实现一下下:

internal func makeCoordinator() -> SwiftUIImagePickerCoordinator {
    SwiftUIImagePickerCoordinator(self)
}

顺便实现一下选择完图片的代理方法吧:

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
    if let uiImage = info[.originalImage] as? UIImage {
        parent.image = uiImage
    }
    parent.presentationMode.wrappedValue.dismiss()
}

别忘了设置一下代理:

picker.delegate = context.coordinator

三:参考

Importing an image into SwiftUI using UIImagePickerController

Last updated