Swift iOS - Прыжок из состояния рано, если обнаружена ошибка - PullRequest
0 голосов
/ 05 декабря 2018

Я использую CoreML и Vision для анализа фотографии, сделанной камерой или импортированной из библиотеки.Как только фотография получена, я запускаю некоторый код, чтобы убедиться, что фотография действительна, и если это так, она возвращает true, иначе возвращает false.Я использую это так:

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 точки, которые могут пойти не так, и мне нужно вернуть false, чтобы я мог выпрыгнуть изфункция и, если она действительна, есть 1 точка, где она может идти правильно, и мне нужно вернуть true.Но так как функция возвращает Bool, я продолжаю получать ошибки при попытке вернуть true или false в следующих точках:

enter image description here

Как мне избавиться от вышеуказанных ошибок?

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
}

Ответы [ 2 ]

0 голосов
/ 05 декабря 2018

Первоначально я собирался использовать завершениеHandlers вместо bool, но я думал, что есть более простой способ, которого нет.@vadian послал мне ссылку в комментариях на аналогичный вопрос SO, в котором говорилось, что то, что я пытаюсь сделать, невозможно, потому что, как сказал Денислава Шентова, операторы return с ошибкой предназначены для блоков, а не для самой функции.

Вот useVisionAndCoreMLToCheckIfIsImageValid подпись кода с использованием 2 completionHandlers вместо возврата 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()
}

, а вот функция use:

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
}
0 голосов
/ 05 декабря 2018

Операторы возврата, для которых вы получаете ошибки, действительно являются операторами возврата для замыканий, например - VNCoreMLRequest (модель: модель) {- возврат для этого блока -} , VNCoreMLRequest (модель: модель) {-возврат для этого блока-} , а не для самой функции useVisionAndCoreMLToCheckIfIsImageValid .

Вам необходимо переработать свою стратегию и понять асинхронную картину в вашем случае.Я настоятельно рекомендую сначала получить некоторые знания по этой теме, а не копировать и вставлять решение, которое вы на самом деле не понимаете.

Некоторые записи в блоге по асинхронному программированию: https://ashfurrow.com/blog/comparative-asynchronous-programming/

...