简体   繁体   English

使用异步 PHPicker 选择图像后执行操作

[英]Perform action after picking image with async PHPicker

Problem问题

Want to perform operation BitwiseAND(UIImage1, UIImage2) this is function of OpenCV framework .想要执行操作 BitwiseAND(UIImage1, UIImage2)这是 OpenCV 框架的 function UIImage1 is already presented in MainVC: UIImage1 已经出现在 MainVC 中:

@IBOutlet weak var presentedImage: UIImageView!

So, UIImage2 must be picked additionally, whenever user wants it.因此,用户需要时,必须另外选择 UIImage2。 Worth to mention:值得一提的是:

@IBOutlet weak var presentedImage: UIImageView! @IBOutlet 弱变量presentedImage:UIImageView!

is also picked with the same PHPicker, as UIImage2也使用与 UIImage2 相同的 PHPicker

Current idea of solving problem...目前解决问题的思路...

Created 2 flags:创建了 2 个标志:

  • First one to check, if current picked image with PHPicker is for第一个检查,如果当前使用 PHPicker 挑选的图像是

@IBOutlet weak var presentedImage: UIImageView! @IBOutlet 弱变量presentedImage:UIImageView!

or for "Bitwise's purpose".或“按位的目的”。

This is the flag:这是旗帜:

private var isBitwisePick: Bool = false
  • Second "flag" determines type of Bitwise to perform ( AND XOR NOR OR )第二个“标志”确定要执行的按位类型( AND XOR NOR OR
 private var bitwiseOperationType: OperationTypes.ControllerTypes.BitwiseTypes?
 enum ControllerTypes{
 /*...*/
    enum BitwiseTypes{ case AND,NOR,XOR,OR }
/*.../
}

Attempt of handling user's image picking尝试处理用户的图像拾取

/* This is switch-case of callback from other viewcontroller.
In our case only this one matters
*/
case .BITWISE_VC(let bitwise):
               
            self.isBitwisePick = true //Pick image for "Bitwise purpose"
            self.bitwiseOperationType = bitwise // determines type of Bitwise 
 
            // config and present PHPicker
            var config = PHPickerConfiguration()
            config.filter = .images
            config.selectionLimit = 1
            let picker = PHPickerViewController(configuration: config)
            picker.delegate = self
            self.present(picker, animated: true)

PHPickerViewControllerDelegate PHPickerViewControllerDelegate

extension MainViewController:  PHPickerViewControllerDelegate{
    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
        dismiss(animated: true)
        print("test before async \(self.isBitwisePick)")
        if let itemProvider = results.first?.itemProvider, itemProvider.canLoadObject(ofClass: UIImage.self){
            let previousImage = self.presentedImage.image
            itemProvider.loadObject(ofClass: UIImage.self){ [weak self] image, error in
                DispatchQueue.main.async { [self] in
                    guard let self = self, let image = image as? UIImage, self.presentedImage.image == previousImage else {
                        return
                    }
                    print("Im in async \(self.isBitwisePick)")
                    if(self.isBitwisePick){
                        switch self.bitwiseOperationType{
                            case .AND:
                                self.presentedImage.image = OpenCVWrapper.bitwiseAND(self.presentedImage.image, with: image)
                                break
                            default:
                                print("the same for XOR OR NOR")
                            break
                        }
                    }
                    else{ self.presentedImage.image = image }
                }
            }
            self.isBitwisePick = false
        }
    }
}

With the line随着线

print(" test before async (self.isBitwisePick)") print(" 异步前测试 (self.isBitwisePick)")

I can see, that flag changed and its value is true我可以看到,该标志已更改,其值为true

However... The line:但是......这条线:

print("Im in async (self.isBitwisePick)") prints value: false print("Im in async (self.isBitwisePick)") 打印值: false

I've just started with swift, read some posts and docs about solutions like DispatchQueue or DispatchGroup... But i couldn't fix it out.我刚刚开始使用 swift,阅读了一些关于 DispatchQueue 或 DispatchGroup 等解决方案的帖子和文档......但我无法解决它。 That's why I'm asking for your help and tips.这就是为什么我要寻求你的帮助和提示。 Thank You for your time:)感谢您的时间:)

Your data structure should be something like您的数据结构应该类似于

private var firstImage: UIImage?
private var secondImage: UIImage?

then you can override setters or apply some other mechanism like然后您可以覆盖设置器或应用其他一些机制,例如

private var firstImage: UIImage? { didSet { reevaluateImagesSet() } }
private var secondImage: UIImage? { didSet { reevaluateImagesSet() } }

private func reevaluateImagesSet() {
    imageView1.image = firstImage
    imageView2.image = secondImage

    if let firstImage = firstImage, let secondImage = secondImage {
        applyCombinedImage(firstImage, secondImage)
    }
}

private func applyCombinedImage(_ firstImage: UIImage, _ secondImage: UIImage) {
    // do the bitwise operation of yours in here
}

Now the only problem is how to define which image you are setting.现在唯一的问题是如何定义您正在设置的图像。 You could use a boolean flag or create a custom class which makes things like so:您可以使用 boolean 标志或创建自定义 class ,这样可以:

   @IBAction private func selectFirstImagePressed() {
        let picker = MyPicker(controller: self)
        self.currentPicker = picker
        picker.selectImage { image in
            self.firstImage = image
        }
   }

   @IBAction private func selectSecondImagePressed() {
        let picker = MyPicker(controller: self)
        self.currentPicker = picker
        picker.selectImage { image in
            self.secondImage = image
        }
   }

This class MyPicker then corresponds to PHPickerViewControllerDelegate and implements the logic to only return an image in a provided closure.然后,此 class MyPicker对应于PHPickerViewControllerDelegate并实现仅在提供的闭包中返回图像的逻辑。 I hope you will have no problems implementing it.我希望你在实施它时不会遇到任何问题。 It is mostly extracting the code that you already have.它主要是提取您已经拥有的代码。

The problem is the line问题是线路

 self.isBitwisePick = false

In your didFinishPicking() function.在您的 didFinishPicking() function 中。 That line will execute before the completion handler of your itemProvider.loadObject(ofClass:) function is called.该行将在调用 itemProvider.loadObject(ofClass:) function 的完成处理程序之前执行。 Then when you check isBitwisePick in your completion handler, it will be false.然后,当您在完成处理程序中检查 isBitwisePick 时,它将是错误的。 You should move that line inside your completion handler.您应该在完成处理程序中移动该行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM