ios - iOS14 中的 UIViewControllerRepresentable 和属性包装器行为,与 CropViewController 一起使用
问题描述
我正在使用“UIImagePickerController”和“CropViewController”来修改从照片库中选择的图像。由于目标 OS 版本为 13+,“UIViewControllerRepresentable”用于处理 SwiftUI 中的这些 UIKit 部分。Xcode 版本为 12.0。
(注)CropViewController 是一个第三方库。来源在这里:https ://github.com/TimOliver/TOCropViewController
我在 iOS14 上启动时发现了一个奇怪的行为,无法找出原因。请帮我!!
以下是我所做的。我在编号从“//**** 1****”到“//**** 3****”的代码中添加了“print()”,以向您展示什么是奇怪的。
[ UIImagePickerController ]
import SwiftUI
struct ImagePicker: UIViewControllerRepresentable {
@Binding var isPresented: Bool // this is a flag used for presenting "UIImagePickerController"
@Binding var materialImage: UIImage? // this is to be passed to "CropViewController"
@Binding var showCropView: Bool // this is a flag used for presenting "CropViewController"
func makeCoordinator() -> ImagePicker.Coordinator {
return ImagePicker.Coordinator(
isPresented: $isPresented,
materialImage: $materialImage,
showCropView: $showCropView
)
}
func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
let picker = UIImagePickerController()
picker.delegate = context.coordinator
picker.sourceType = .photoLibrary
return picker
}
func updateUIViewController(_ uiViewController: UIImagePickerController,
context: UIViewControllerRepresentableContext<ImagePicker>) {}
}
extension ImagePicker {
class Coordinator: NSObject, UINavigationControllerDelegate {
@Binding var isPresented: Bool
@Binding var materialImage: UIImage?
@Binding var showCropView: Bool
public init(isPresented: Binding<Bool>, materialImage: Binding<UIImage?>, showCropView: Binding<Bool>) {
self._isPresented = isPresented
self._materialImage = materialImage
self._showCropView = showCropView
}
}
}
extension ImagePicker.Coordinator: UIImagePickerControllerDelegate {
public func imagePickerController(
_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
DispatchQueue.mainSyncSafe {
self.materialImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage
isPresented = false // close UIImagePicker
showCropView = true // launch CropViewController
print("materialImage @ImagePicker: \(materialImage)") // ****1****
}
}
public func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
isPresented = false
}
}
[作物视图控制器]
import SwiftUI
import CropViewController
struct CropView: UIViewControllerRepresentable {
var materialImage: UIImage? // selected image with ImagePickerController
@Binding var newImage: UIImage? // modified image with CropViewController
@Binding var isPresented: Bool // this is a flag to show/hide CropViewController
init(materialImage: UIImage?, newImage: Binding<UIImage?>, isPresented: Binding<Bool>){
self.materialImage = materialImage
self._newImage = newImage
self._isPresented = isPresented
}
func makeCoordinator() -> CropView.Coordinator {
return CropView.Coordinator(
isPresented: $isPresented,
newImage: $newImage
)
}
func makeUIViewController(context: UIViewControllerRepresentableContext<CropView>) -> CropViewController {
let cropViewController = CropViewController(image: materialImage ?? UIImage())
print("materialImage @CropView: \(materialImage)") // ****2****
cropViewController.delegate = context.coordinator
return cropViewController
}
func updateUIViewController(_ uiViewController: CropViewController,
context: UIViewControllerRepresentableContext<CropView>) {}
}
extension CropView {
class Coordinator: NSObject {
@Binding var isPresented: Bool
@Binding var newImage: UIImage?
public init(isPresented: Binding<Bool>, newImage: Binding<UIImage?>) {
self._isPresented = isPresented
self._newImage = newImage
}
}
}
extension CropView.Coordinator: ObservableObject, CropViewControllerDelegate {
func cropViewController(_ cropViewController: CropViewController, didCropToImage image: UIImage, withRect cropRect: CGRect, angle: Int) {
newImage = image
isPresented = false
NotificationCenter.default.post(name: .imageSelected, object: nil, userInfo: nil)
}
func cropViewController(_ cropViewController: CropViewController, didFinishCancelled cancelled: Bool) {
isPresented = false
}
}
[内容.swift]
import SwiftUI
struct Content: View {
@State var showImagePicker: Bool = false // flag for show/hide UIImagePickerController
@State var showCropView: Bool = false // flag for show/hide CropViewController
@State var materialImage: UIImage? // selected image with UIImagePickerController
@State var newImage: UIImage? // modified Image with CropViewController
var body: some View {
VStack{
// show some views
Spacer().frame(height: 0).sheet(isPresented: $showImagePicker) {
ImagePicker(isPresented: self.$showImagePicker, materialImage: self.$materialImage, showCropView: self.$showCropView)
}
Spacer().frame(height: 0.0).sheet(isPresented: self.$showCropView) {
CropView(materialImage: self.materialImage, newImage: self.$newImage, isPresented: self.$showCropView)
}
}
.onReceive( NotificationCenter.default.publisher(for: .imageSelected) ){_ in
print("materialImage @Content: \(materialImage)") // ****3****
}
}
}
使用 iOS13.5 的模拟器启动时,调试打印如下。有一条未知消息,但这很好。
materialImage @ImagePicker: Optional(<UIImage:0x600002810510 anonymous {4032, 3024}>) // ****1****
materialImage @CropView: Optional(<UIImage:0x600002810510 anonymous {4032, 3024}>) // ****2****
2020-09-22 sbx[ ] [Common] _BSMachError: port c603; (os/kern) invalid capability (0x14) "Unable to insert COPY_SEND"
materialImage @CreateAdv_SwiftUIView: Optional(<UIImage:0x600002810510 anonymous {4032, 3024}>) // ****3****
使用iOS14的模拟器,CropView屏幕是黑色的,调试打印如下。“materialImage @CropView”为零。更奇怪的是,在关闭此裁剪视图屏幕(使用取消按钮)并再次选择图像后,一切正常(我可以选择和修改图像)。
iOS14有bug吗?还是我的实施不好?
materialImage @ImagePicker: Optional(<UIImage:0x600003f3cf30 anonymous {4032, 3024}>) // ****1****
materialImage @CropView: nil // ****2****
2020-09-22 sbx[ ] [ScrollView] UIScrollView is ignoring an attempt to set zoomScale to a non-finite value: inf
2020-09-22 sbx[ ] [Unknown process name] CGContextTranslateCTM: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
materialImage @CreateAdv_SwiftUIView: Optional(<UIImage:0x600003f3cf30 anonymous {4032, 3024}>) // ****3****
2020-09-22 sbx[ ] [] nw_protocol_get_quic_image_block_invoke dlopen libquic failed
我希望你的建议!谢谢!!
解决方案
推荐阅读
- node.js - 如何在猫鼬的另一个集合中找到一个集合
- wordpress - 为什么我的 wordpress 所见即所得编辑器不断注入奇怪的 html 代码?
- javascript - 我可以取消选中 Datagrid Material-ui 中单击按钮上的选中复选框吗
- javascript - 如何设置 echarts boxplot x 轴标签?
- java - 当工作空间中存在文件时,Jenkins 抛出 NoSuchFileException
- raspberry-pi - 如何从 SD 卡启动 Raspberry Pi 计算模块 4(带有 eMMC)
- python-3.x - Flask:无头文件上传
- php - 如何在供应商包类中实现应用模型(类)?
- node.js - 如何获取我已绑定为使用 ldapjs 的用户的个人资料
- coordinates - 如何使用 turfjs 库生成两个经度和纬度之间的点