为什么NSSpeechSynthesizer没有调用其委托方法?

时间:2017-12-02 06:07:39

标签: swift cocoa text-to-speech

当我在NSSpeechSynthesizer实例上调用startSpeaking(String)方法时,如果设置了委托,则会发生说话,但以下委托方法永远不会触发:

speechSynthesizer(_ sender: NSSpeechSynthesizer, 
              willSpeakWord characterRange: NSRange, 
                         of string: String)

func speechSynthesizer(_ sender: NSSpeechSynthesizer, 
          didFinishSpeaking finishedSpeaking: Bool)

为什么呢?我正在使用Swift 4; XCode 9.1; MacOS 10.13.1

重现步骤:

编译并运行以下命令:

import AppKit

class SynthDelegate: NSObject, NSSpeechSynthesizerDelegate {

    var str = ""

    func speechSynthesizer(_ sender: NSSpeechSynthesizer, willSpeakWord characterRange: NSRange, of string: String) {
        str = "spoke a word"
    }

    func speechSynthesizer(_ sender: NSSpeechSynthesizer, didFinishSpeaking finishedSpeaking: Bool) {
        str = "finished speaking"
    }

}

let mySpeaker = NSSpeechSynthesizer()

let myDelegate = SynthDelegate()

mySpeaker.delegate = myDelegate

mySpeaker.startSpeaking("test string to read aloud")

sleep(5) // keep alive while speaking

print(myDelegate.str)

预期结果:

“说完了”

实际结果:

“”

更新

基于OOPers的优秀答案,以下是新测试项目的工作原理:

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {



    func applicationDidFinishLaunching(_ aNotification: Notification) {
        // Insert code here to initialize your application

        let mySpeaker = NSSpeechSynthesizer()
        let myDelegate = SynthDelegate()
        mySpeaker.delegate = myDelegate
        mySpeaker.startSpeaking("test string to read aloud")


        Timer.scheduledTimer(withTimeInterval: 5.0, repeats: false) {_ in
            print(myDelegate.str)

        }
    }

    func applicationWillTerminate(_ aNotification: Notification) {
        // Insert code here to tear down your application
    }


}


class SynthDelegate: NSObject, NSSpeechSynthesizerDelegate {
    var str = ""

    func speechSynthesizer(_ sender: NSSpeechSynthesizer, willSpeakWord characterRange: NSRange, of string: String) {
        str = "spoke a word"
        print(str)
    }

    func speechSynthesizer(_ sender: NSSpeechSynthesizer, didFinishSpeaking finishedSpeaking: Bool) {
        str = "finished speaking"
        print(str)
    }
}

1 个答案:

答案 0 :(得分:1)

您是否在Playground中测试代码?无论如何,您不应该在您的应用中拨打sleep(),包括游乐场代码。

它阻止了使框架工作所需的许多活动,例如调用委托方法。当您需要在延迟后执行某些代码时,可以使用Timer

游乐场可测试:

import AppKit

class SynthDelegate: NSObject, NSSpeechSynthesizerDelegate {
    var str = ""

    func speechSynthesizer(_ sender: NSSpeechSynthesizer, willSpeakWord characterRange: NSRange, of string: String) {
        str = "spoke a word"
        print(str)
    }

    func speechSynthesizer(_ sender: NSSpeechSynthesizer, didFinishSpeaking finishedSpeaking: Bool) {
        str = "finished speaking"
        print(str)
    }
}

let mySpeaker = NSSpeechSynthesizer()
let myDelegate = SynthDelegate()
mySpeaker.delegate = myDelegate
mySpeaker.startSpeaking("test string to read aloud")

import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true

Timer.scheduledTimer(withTimeInterval: 5.0, repeats: false) {_ in
    print(myDelegate.str)
    PlaygroundPage.current.finishExecution()
}