2017-12-02 4 views
0

Wenn ich die startSpeaking (String) -Methode auf einer NSSpeechSynthesizer Instanz aufrufen, mit einem Delegierten-Set, tritt zu sprechen, aber die folgenden Delegatmethoden nie Feuer:Warum ruft NSSpeechSynthesizer seine Delegatmethoden nicht auf?

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

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

Warum? Ich benutze Swift 4; XCode 9.1; MacOS 10.13.1

Schritte zum Reproduzieren:

Compile und führen die folgenden Schritte aus:

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) 

Erwartete Ergebnisse:

"zu Ende gesprochen"

Actual Ergebnisse:

""

aktualisieren

Aufbauend auf OOPers ausgezeichnete Antwort, die folgenden Arbeiten in einem neuen Testprojekt:

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) 
    } 
} 

Antwort

1

testen Sie den Code in dem Spielplatz? Wie auch immer, du solltest niemals sleep() in deinen Apps anrufen, einschließlich Playground-Code.

Es verhindert viele Aktivitäten, die zum Funktionieren von Frameworks erforderlich sind, wie zum Beispiel den Aufruf von Delegate-Methoden. Sie können Timer verwenden, wenn Sie nach einer Verzögerung Code ausführen müssen.

Prüfbar im Spielplatz:

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() 
} 
+0

Ok, das es auf Spielplätzen arbeiten wird! Was beweist (ich denke) es ist kein Fehler in NSSpeechSynthesizer. Was wäre das Äquivalent zum Testen in einem XCTestCase-Test? – Mark

+1

@Mark, XCTestCase ist kein gutes Werkzeug zum Testen dieser Art von asynchronem Feature, und ich habe nicht versucht, daran zu arbeiten. Wenn das Testen in einem XCTestCase eine Voraussetzung für Sie ist, sollten Sie Ihre Frage besser auf den neuesten Stand bringen und sie klären, damit sie an jemanden mit mehr Erfahrung in XCTestCase appelliert. – OOPer

Verwandte Themen