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

3

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

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

我想进行设置

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

然后定期使用NSSpeechStatusNumberOfCharactersLeft更新进度指示器,根据苹果公司的文档,该指示器应该达到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))

有抛出运行时异常的代码。你有什么想法吗?提前感谢!


好的,现在情况有点奇怪。这个键NSSpeechStatusNumberOfCharactersLeft只有在我重新启动电脑后才能正确返回值。(不要问我是怎么发现的:P)而且只能通过以下方式访问它:let count = try speechSynthesizer.objectForProperty(NSSpeechStatusProperty).objectForKey(NSSpeechStatusNumberOfCharactersLeft) - Pink Pegasus
1个回答

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

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

没有错误信息(由于我手头没有Swift 2编译器),我猜测失败的原因是objectForProperty的返回值未知,所以您无法在其中查找值。
这是用于测试此功能的我的快速和简单的Swift 3 playground:
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回调来完成剩余部分,删除进度UI或执行其他操作。


Swift 2.2 对那个调用不太满意,所以我将其修改为:let statusDict = try! speechSynthesizer.objectForProperty(NSSpeechStatusProperty) as! [String: Any] print(statusDict[NSSpeechStatusNumberOfCharactersLeft]) 但在运行时它抛出了一个异常。 - Pink Pegasus
对于Swift 2.x来说,你可能需要使用[String: AnyObject],而不是[String: Any] - rickster
尝试过了,但没有成功。然后更新了Xcode,用Swift 2.3和3尝试了一下,还是不行。接着我在一个3 Playground中尝试了你的代码,但它无法运行,只是一直尝试“运行Playground”。也许我的开发环境有问题:( - Pink Pegasus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接