使用NSSpeechStatusNumberOfCharactersLeft更新NSSpeechSynthesizer的进度指示器

时间:2016-09-15 03:50:55

标签: swift macos

我是SwiftOS X编程的新手。我正在尝试使用进度监视器来指示我的语音合成器说话文本的进度。

let speechSynthesizer = NSSpeechSynthesizer()
speechSynthesizer.delegate = self;
speechSynthesizer.startSpeakingString(contents)

我想设置

progressIndicator.maxValue = Double(NSSpeechStatusNumberOfCharactersLeft.characters.count)

然后使用NSSpeechStatusNumberOfCharactersLeft定期更新progressIndicator,根据Apple的文档,该值应为0。

我尝试访问此密钥的每一种方式都返回相同的不准确数字,所以我显然没有正确使用它。我找到的唯一例子是Objective-C

NSNumber *n = [[self.speechSynth objectForProperty:NSSpeechStatusProperty error:NULL] objectForKey:NSSpeechStatusNumberOfCharactersLeft];

我尝试将其翻译为Swift,但仍然没有骰子。

let count = try speechSynthesizer.objectForProperty(NSSpeechStatusProperty).objectForKey(NSSpeechStatusNumberOfCharactersLeft)

我也试过

speechSynthesizer.valueForKey(NSSpeechStatusNumberOfCharactersLeft))
speechSynthesizer.valueWithName(NSSpeechStatusNumberOfCharactersLeft, inPropertyWithKey: NSSpeechStatusProperty))

抛出运行时异常。有什么想法吗?提前谢谢!

1 个答案:

答案 0 :(得分:1)

你的第二次尝试非常接近正确:

let count = try speechSynthesizer.objectForProperty(NSSpeechStatusProperty).objectForKey(NSSpeechStatusNumberOfCharactersLeft)

没有错误消息(因为我没有方便的Swift 2编译器)我猜测失败的原因是objectForProperty的返回值不知道是字典,所以你不能在其中查找值。

这是我的快速&脏Swift 3游乐场测试这个:

import PlaygroundSupport
import Cocoa

let synth = NSSpeechSynthesizer()
synth.startSpeaking("I'm not standing still, I am lying in wait")

// quick way to test for progress without setting up an app and delegate
PlaygroundPage.current.needsIndefiniteExecution = true
let timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in
    let statusDict = try! synth.object(forProperty: NSSpeechStatusProperty) as! [String: Any]
    print(statusDict[NSSpeechStatusNumberOfCharactersLeft])
}

(显然,如果您在具有合成器代表的应用程序中运行此功能,则不需要所有计时器内容或游乐场业务。)

关键位(没有双关语)是转换objectForProperty的返回值,以便Swift知道它是一个字典,然后查找该字典中的字符数。

现在,这段代码运行正常,但它并不完全适用于设置进度条 - 当合成器完成发言时,NSSpeechStatusNumberOfCharactersLeft可能是一些非零值。 (在这种情况下,另一个状态键NSSpeechStatusOutputBusy将变为false。)因此,您的进度条将达不到100%,您可以使用NSSpeechStatusOutputBusy键或代理didFinishSpeaking回调以完成剩下的任务,删除进度用户界面等等。