处理语音中没有互联网连接错误

时间:2017-05-18 16:20:22

标签: ios error-handling swift3

我有一个带有longPressGestureRecognizer的UIButton,如果用户点击并按住按钮,语音识别开始,释放按钮,语音文本出现在textField中 它工作正常,但Apple的Speech Framework需要有效的互联网连接。出于这个原因,我希望用户通过警报获得相应的消息。 就是这样,我试着自己处理它:

 enum InternetConnectionError: Error {
   case noInternet 
   case lowInternetSpeed
 }

 // start the recognition
 @IBAction func longPressAddArticles(_ sender: UILongPressGestureRecognizer) {
    if sender.state == .began {
        do {
            try startSession()
        } catch  InternetConnectionError.noInternet {
            displayInformationAlert(message: "Sorry, please check your internet connection!")
        } catch InternetConnectionError.lowInternetSpeed {
            displayInformationAlert(message: "Sorry your internet is to slow!")
        // catch All other errors
        } catch let error as Error {
            displayInformationAlert(message: "Unknown error!")
        }
    } else if sender.state == .ended {
        if audioEngine.isRunning {
            audioEngine.stop()
            speechRecognitionRequest?.endAudio()
        }
    }
}

    func displayInformationAlert(message: String) {
    let alert = UIAlertController(title: "Attention", message: message, preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "OK", style: .cancel))
    present(alert, animated: true)
}

 private func startSession() throws {
    // check if a previous recognition task is running, and if so cancel it
    if let recognitionTask = speechRecognitionTask {
        recognitionTask.cancel()
        self.speechRecognitionTask = nil
    }

    let audioSession = AVAudioSession.sharedInstance()
    try audioSession.setCategory(AVAudioSessionCategoryRecord)

    speechRecognitionRequest = SFSpeechAudioBufferRecognitionRequest()

    guard let recognitionRequest = speechRecognitionRequest else {
        throw InternetConnectionError.noInternet
    }

    guard let inputNode = audioEngine.inputNode else {
        throw InternetConnectionError.lowInternetSpeed
    }

    let recordingFormat = inputNode.outputFormat(forBus: 0)
    inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { buffer, _ in
        self.speechRecognitionRequest?.append(buffer)
    }

    audioEngine.prepare()

    do {
        try audioEngine.start()
    } catch {
        displayInformationAlert(message: "The recognition could'n start!")
    }

    speechRecognitionRequest?.shouldReportPartialResults = false
    speechRecognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest) { result, error in
        var finished = false

        if let result = result {
            let articleName = result.bestTranscription.formattedString
            if (self.checkIfShopExists(name:articleName)) {
                self.delegate?.openExistShopWith(name: articleName)
            } else {
                self.createNewArticle(name: articleName)
            }
            finished = result.isFinal
        }

        if error != nil || finished {
            self.audioEngine.stop()
            inputNode.removeTap(onBus: 0)
            self.speechRecognitionRequest = nil
            self.speechRecognitionTask = nil
            self.btnRecordButton.isEnabled = true
        }
    }

}

如果我在飞行模式下开启iPhone,启动应用程序,多次按下按钮,应用程序崩溃,无需一些有用的崩溃报告

enter image description here 一些想法?

1 个答案:

答案 0 :(得分:0)

我使用此功能检查互联网是否是您功能的第一行。然后只使用一个保护声明,只有在有互联网的情况下才能继续。

func isInternetAvailable() -> Bool
{
    var zeroAddress = sockaddr_in()
    zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
    zeroAddress.sin_family = sa_family_t(AF_INET)

    let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
        $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in
            SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
        }
    }

    var flags = SCNetworkReachabilityFlags()
    if !SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) {
        return false
    }
    let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
    let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
    return (isReachable && !needsConnection)
}