Swift iOS - 如果发现错误则提前跳出条件

Swift iOS -Jump out of condition early if error is found

我正在使用 CoreML 和 Vision 分析用相机拍摄或从图库导入的照片。获得照片后,我 运行 使用一些代码来确保照片有效,如果有效,则 return 为真,否则 return 为假。我是这样使用的:

func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {

    if let error = error {
        // display alert there is a problem
        return
    }

    guard let imageData = photo.fileDataRepresentation(), let previewImage = UIImage(data: imageData) else {
        // display alert there is a problem
        return
    }

    if useVisionAndCoreMLToCheckIfIsImageValid(image: previewImage) {

        tableData.append(previewImage)

    } else {

        // display alert image was not valid
    }
}

问题是 useVisionAndCoreMLToCheckIfIsImageValid 函数中有 4 个点可能出错,我需要 return false 这样我才能跳出函数,如果它有效,则有 1 点可以正确执行,我需要 return true。但是由于函数 returns a Bool 我在尝试 return truefalse 时不断出错:

如何消除上述错误?

func useVisionAndCoreMLToCheckIfIsImageValid(image: UIImage) -> Bool {

    if let cgImage = image.cgImage {

        let foodModel = CustomFoodModel()
        guard let model = try? VNCoreMLModel(for: foodModel.model) else {
            return false
        }

        let request = VNCoreMLRequest(model: model) { [weak self](request, error) in

            if let error = error {
                // 1st point - if there is an error return false
                return false
            }


            guard let results = request.results as? [VNClassificationObservation], let topResult = results.first else {
                // 2nd point - if there is a nil value here return false
                return false
            }

            if topResult.confidence > 0.8 {

                // 3rd point - if confidence is greater then 80% return true
                return true
            } else {

                // 4th point - if confidence is less then 80% return false
                return false
            }
        }

        let handler = VNImageRequestHandler(cgImage: cgImage, options: [:])
        DispatchQueue.global(qos: .userInitiated).async { [weak self] in
            do {

                try handler.perform([request])

            } catch let err as NSError {


                // 5th point - if there is a try error return false                   
                return false
            }
        }
    }

    // if the cgImage is nil return false
    return false
}

你收到错误的 return 语句确实是闭包的 return 语句,例如- VNCoreMLRequest(model: model) { - return 这个块 - }, VNCoreMLRequest(model: model) { -return 此块 - } 而不是 useVisionAndCoreMLToCheckIfIsImageValid 函数本身。

您需要重新制定策略并了解您案例中的异步情况。 我强烈建议首先了解有关该主题的一些知识,而不是复制粘贴您并不真正理解的解决方案。

一些关于异步编程的博客post: https://ashfurrow.com/blog/comparative-asynchronous-programming/

我最初打算使用 completionHandlers 而不是 bool,但我认为有更简单的方法,但没有。 @vadian 在评论中给我发了一个 link 到一个类似的 SO 问题,基本上说我想做的事情无法完成,因为正如 DenislavaShentova 的回答所说,有错误的 return 语句是针对块和不是函数本身。

这里是 useVisionAndCoreMLToCheckIfIsImageValid 代码签名,使用 2 completionHandlers 而不是 returning Bool

func useVisionAndCoreMLToCheckIfIsImageValid(image: UIImage, falseCompletion: @escaping ()->(), trueCompletion: @escaping ()->()) {

    if let cgImage = image.cgImage {

        let foodModel = CustomFoodModel()
        guard let model = try? VNCoreMLModel(for: foodModel.model) else {
            falseCompletion()
            return
        }

        let request = VNCoreMLRequest(model: model) { [weak self](request, error) in

            if let error = error {
                // 1st point - run code for false
                falseCompletion()
                return
            }


            guard let results = request.results as? [VNClassificationObservation], let topResult = results.first else {
                // 2nd point - run code for false
                falseCompletion()
                return
            }

            if topResult.confidence > 0.8 {

                // 3rd point - run code for false
                trueCompletion()
            } else {

                // 4th point - run code for false
                falseCompletion()
            }
        }

        let handler = VNImageRequestHandler(cgImage: cgImage, options: [:])
        DispatchQueue.global(qos: .userInitiated).async { [weak self] in
            do {

                try handler.perform([request])

            } catch let err as NSError {


                // 5th point - run code for false
                falseCompletion()
            }
        }
    }

    // if the cgImage is nil run code for false
    falseCompletion()
}

这里是使用的函数:

func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {

    if let error = error {
        // display alert there is a problem
        return
    }

    guard let imageData = photo.fileDataRepresentation(), let previewImage = UIImage(data: imageData) else {
        // display alert there is a problem
        return
    }

    useVisionAndCoreMLToCheckIfIsImageValid(image: previewImage, falseCompletion: thereIsAProblem, trueCompletion: imageIsValid)

}

func imageIsValid() {

    tableData.append(previewImage)
}

func thereIsAProblem() {

    // do something
}