05.如何在SwiftUI中使用ImagePicker?
一:问题
我的新项目中尝试性的使用了
SwiftUI
进行了一部分功能的构建。 但当我需要访问相册选择图片的时候,缺犯难了。 报出了下面的错误:因为原有的一些代理需要要求
NSObjectProtocol
而我们SwifUI中的视图用的是Struct
而系统并没有提供在SwiftUI
下调用相册的相关API,所以这里只能考虑自己去封装了。
二: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
就已经是一个标准的SwiftUI
的View
了。
当创建一个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
Was this helpful?