我正在创建一个MacOS应用程序,该应用程序从制表符分隔的文本文件生成对话框文件。文本文件格式为(输出文件名)[tab](与该文件说话的文本)。我让程序在主线程中完美运行,但这当然阻止了UI。当我将应用程序的内容移动到用户启动的线程时,我取消阻止了UI,但现在它偶尔会随机地说出扬声器而不是文件。仍然会创建一个文件,但它的持续时间为零。如果脚本包含1,000行,那么它可能会完美地完成整个过程,或者它可能会#34;说"他们中的十个或更多是说话人。它每次几乎总是不同的线。
这是与文件对话的代码:
// Set URL to save file to disk
if let speechFileURL = NSURL(string: speechFilePath) {
speechSynth.startSpeakingString(spokenText, toURL: speechFileURL) // Speak to file
}
else {
dialogAlert("Invalid File: ", text: speechFileName)
}
while(NSSpeechSynthesizer.isAnyApplicationSpeaking() == true) {
if self.gUserClickedStop {
speechSynth.stopSpeaking()
self.gIsSpeaking = false
break
}
}
这是对解析脚本并生成语音文件的函数的调用:
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)) { [unowned self] in
self.parseTheScript()
}
如上所述,调用parseTheScript()而不将其包装在Grand Central Dispatch调用中使其完美地工作,除了阻塞问题。
我刚接触Swift的编程和多线程编程的想法,所以我确定我做错了什么,但我很难解决如何解决这个问题
提前感谢您的帮助。
编辑以添加...
这是解析文本文件并生成对话文件的整个函数:
// This opens the text file and generates the spoken audio files
func parseTheScript() {
let filemgr = NSFileManager.defaultManager()
print("Chosen path: \(scriptFileTextField.stringValue)") // debug
if filemgr.fileExistsAtPath(scriptFileTextField.stringValue) {
print("File exists")
do {
outputFilename.stringValue = ""
scriptToSpeak.stringValue = ""
outputFilename.hidden = false
scriptToSpeak.hidden = false
progressBar.minValue = 0
progressBar.doubleValue = 0.0
progressBar.hidden = false
filenameLabel.hidden = false
let text = try String(contentsOfFile: scriptFileTextField.stringValue, encoding: NSUTF8StringEncoding)
let lines: [String] = text.componentsSeparatedByString("\n")
var progressEndValue = Double(lines.count)
progressBar.maxValue = progressEndValue
let speechSynth = NSSpeechSynthesizer.init()
let theVoice = gVoiceList[voiceListPopup.indexOfSelectedItem - 1] // Not sure why it's off by one
speechSynth.setVoice(theVoice)
for line in lines {
let thisLine: [String] = line.componentsSeparatedByString("\t") // Split the line at the tab character
if (thisLine.count == 2) { // Did the line split into two parts?
let speechFileName = thisLine[0]
let spokenText = thisLine[1]
outputFilename.stringValue = speechFileName
scriptToSpeak.stringValue = spokenText
let speechFilePath = destinationFolderTextField.stringValue + speechFileName + ".aif" // Build the path string for the output speech file
print("Filename: \(speechFilePath)")
print("SpokenText: \(spokenText)")
if(gSpeakToFile) {
// Set URL to save file to disk
if let speechFileURL = NSURL(string: speechFilePath) {
speechSynth.startSpeakingString(spokenText, toURL: speechFileURL) // Speak to file
}
else {
dialogAlert("Invalid File: ", text: speechFileName)
}
}
else {
speechSynth.startSpeakingString(spokenText) // Speak to audio output
}
while(NSSpeechSynthesizer.isAnyApplicationSpeaking() == true) {
if self.gUserClickedStop {
speechSynth.stopSpeaking()
self.gIsSpeaking = false
break
}
}
progressBar.incrementBy(1.0)
}
if gUserClickedStop {
gUserClickedStop = false
gIsSpeaking = false
progressEndValue = 0
generateButton.title = "Start"
break
}
}
gIsSpeaking = false
progressBar.doubleValue = progressEndValue
generateButton.title = "Start"
filenameLabel.hidden = true
outputFilename.stringValue = ""
scriptToSpeak.stringValue = ""
} catch let error as NSError {
dialogAlert("Error:", text: String(error.localizedDescription))
print("Error: \(error)")
}
} else {
print("File does not exist")
}
}