当另一个结束时运行一个函数,iOS,Swift

时间:2021-04-09 16:04:48

Im trying to call a function when another one ends but I keep getting an error that tells me the image is not above 0 pixels high and wide so I presume it hasn't got the image before the function is called. when I add a breakpoint where the function to call the OCR the app doesn't show the image on the screen at this point which is why I came to that conclusion.

我试图在另一个结束时调用一个函数,但我不断收到一个错误,告诉我图像不高于0像素高,所以我认为它在调用函数之前没有得到图像。当我添加一个断点,其中调用OCR的函数应用程序此时不会在屏幕上显示图像,这就是我得出结论的原因。

here is the error I get from the ocr.

这是我从ocr得到的错误。

NSAssert( widthOfImage > 0 && heightOfImage > 0, @"Passed image must not be empty - it should be at least 1px tall and wide");

NSAssert(widthOfImage> 0 && heightOfImage> 0,@“传递的图像不能为空 - 它应至少为1px高和宽”);

below is my console readout where I placed prints to see the flow.

下面是我的控制台读数,我放置打印以查看流程。

Tony 1 Requested.... Tony 3 run OCR.... Tony 2 Handle Rectangle.... Tony: Corected image here...... (lldb)

Tony 1请求...... Tony 3运行OCR .... Tony 2处理矩形.... Tony:这里的核心图像......(lldb)

Below is my code. should i have in a completion that makes sure the function is not called until the image is in place?.

以下是我的代码。我应该在完成时确保在图像到位之前不调用该函数吗?

func startOCR() {
        swiftOCRInstance.recognize(correctedImageView.image!) {recognizedString in
            print(recognizedString)
            self.classificationLabel.text = recognizedString
        }
    }


lazy var rectanglesRequest: VNDetectRectanglesRequest = {
    print("Tony 1 Requested....")
    return VNDetectRectanglesRequest(completionHandler: self.handleRectangles)



}()

func handleRectangles(request: VNRequest, error: Error?) {
    guard let observations = request.results as? [VNRectangleObservation]
        else { fatalError("unexpected result type from VNDetectRectanglesRequest") }
    guard let detectedRectangle = observations.first else {
        DispatchQueue.main.async {
            self.classificationLabel.text = "No rectangles detected."
        }
        return
    }
    let imageSize = inputImage.extent.size

    // Verify detected rectangle is valid.
    let boundingBox = detectedRectangle.boundingBox.scaled(to: imageSize)
    guard inputImage.extent.contains(boundingBox)
        else { print("invalid detected rectangle"); return }

    // Rectify the detected image and reduce it to inverted grayscale for applying model.
    let topLeft = detectedRectangle.topLeft.scaled(to: imageSize)
    let topRight = detectedRectangle.topRight.scaled(to: imageSize)
    let bottomLeft = detectedRectangle.bottomLeft.scaled(to: imageSize)
    let bottomRight = detectedRectangle.bottomRight.scaled(to: imageSize)
    let correctedImage = inputImage
        .cropped(to: boundingBox)
        .applyingFilter("CIPerspectiveCorrection", parameters: [
            "inputTopLeft": CIVector(cgPoint: topLeft),
            "inputTopRight": CIVector(cgPoint: topRight),
            "inputBottomLeft": CIVector(cgPoint: bottomLeft),
            "inputBottomRight": CIVector(cgPoint: bottomRight)
            ])
    //          .applyingFilter("CIColorControls", parameters: [
    //                kCIInputSaturationKey: 0,
    //                kCIInputContrastKey: 32
    //            ])


    // Show the pre-processed image
    DispatchQueue.main.async {
        self.correctedImageView.image = UIImage(ciImage: correctedImage)
        if self.correctedImageView.image != nil {
            print("Tony 2 Handle Rectangle....")
            print("Tony: Corected image here......")

        }else {
            print("Tony: No corected image......")
        }

    }
    print("Tony 3 run OCR....")
    self.startOCR()
}

I also get a purple error the says the UIImage should be used on the main thread in the pic below...

我还得到一个紫色错误,说UIImage应该在下面的图片的主线程上使用...

当另一个结束时运行一个函数,iOS,Swift

1 个解决方案

#1


0  

You need to use the main thread whenever you're working with UIImageView, or any other UIKit class (unless otherwise noted, such as when constructing UIImages on background threads).

每当您使用UIImageView或任何其他UIKit类时,您都需要使用主线程(除非另有说明,例如在后台线程上构建UIImages时)。

You can use GCD to do this on the main thread.

您可以使用GCD在主线程上执行此操作。

DispatchQueue.main.async {
    //Handle UIKit actions here
}

Source: Apple Documentation

来源:Apple文档

Threading Considerations: Manipulations to your application’s user interface must occur on the main thread. Thus, you should always call the methods of the UIView class from code running in the main thread of your application. The only time this may not be strictly necessary is when creating the view object itself, but all other manipulations should occur on the main thread.

线程注意事项:对应用程序的用户界面进行操作必须在主线程上进行。因此,您应该始终从应用程序主线程中运行的代码调用UIView类的方法。这可能不是绝对必要的唯一时间是创建视图对象本身,但所有其他操作应该在主线程上发生。

#1


0  

You need to use the main thread whenever you're working with UIImageView, or any other UIKit class (unless otherwise noted, such as when constructing UIImages on background threads).

每当您使用UIImageView或任何其他UIKit类时,您都需要使用主线程(除非另有说明,例如在后台线程上构建UIImages时)。

You can use GCD to do this on the main thread.

您可以使用GCD在主线程上执行此操作。

DispatchQueue.main.async {
    //Handle UIKit actions here
}

Source: Apple Documentation

来源:Apple文档

Threading Considerations: Manipulations to your application’s user interface must occur on the main thread. Thus, you should always call the methods of the UIView class from code running in the main thread of your application. The only time this may not be strictly necessary is when creating the view object itself, but all other manipulations should occur on the main thread.

线程注意事项:对应用程序的用户界面进行操作必须在主线程上进行。因此,您应该始终从应用程序主线程中运行的代码调用UIView类的方法。这可能不是绝对必要的唯一时间是创建视图对象本身,但所有其他操作应该在主线程上发生。