Programmieren mit Swift - Für macOS und iOS
Programmieren mit Swift - Für macOS und iOS
Delegates im Einsatz

Mit Hilfe des delegate können nun auch die Schönheitsfehler der Sprachausgabe-Anwendung gelöst werden, denn zwei Dinge sind am Programm zu bemängeln. Man kann auf Schweigen klicken, auch wenn gar keine Sprachausgabe aktiv ist. Ebenfalls ist es möglich, eine weitere Sprachausgabe zu starten, während noch eine aktive Ausgabe läuft. Beides soll nicht möglich sein.

Der einfachste Weg, das Anklicken zu verhindern, ist es, die Schaltflächen zu deaktivieren. Dazu benötigt man zunächst zwei weitere Outlet, die dann im Interface Builder mit den Button verbunden werden müssen.
IBOutlet NSButton *speakButton;
IBOutlet NSButton *silenceButton;
Nach Programmstart soll der silenceButton inaktiv sein, da er erst eine Funktion haben soll, wenn eine Sprachausgabe läuft. Wie alle Eigenschaften, die man zum Start setzen will, ist awakeFromNib genau die richtige Methode dafür, als Alternative natürlich auch direkt im Interface Builder.
-(void)awakeFromNib
{
    [silenceButton setEnabled:
FALSE];
    mySpeechSynth = [[NSSpeechSynthesizer alloc] initWithVoice:
nil];
    [mySpeechSynth setDelegate:
self];
}
Wird auf Sprechen geklickt, muss der speakButton deaktiviert und der silenceButton aktiviert werden. Jetzt kann die Sprachausgabe abgebrochen werden, aber eine neue, weitere Sprachausgabe kann nicht mehr gestartet werden.
- (IBAction)speak:(id)sender
{
    [speakButton setEnabled:
FALSE];
    [silenceButton setEnabled:
TRUE];
    NSString *aText = [inputTextField stringValue];
    [mySpeechSynth startSpeakingString:aText];
}
Genau das Gegenteil soll passieren, wenn auf den Schweigen Button geklickt wird. Die Sprachausgabe wird angehalten, und die Schaltflächen nehmen wieder ihren Ausgangszustand ein.
- (IBAction)silence:(id)sender
{
    [speakButton setEnabled:
TRUE];
    [silenceButton setEnabled:
FALSE];
    [mySpeechSynth stopSpeaking];
}
Genau so ist es, wenn die Sprachausgabe auf natürlichem Wege endet. Auch dann müssen die Button wieder in den Ausgangszustand, um eine weitere Ausgabe zu ermöglichen. Mit Hilfe des delegate und der didFinishSpeaking-Nachricht wird der Controller automatisch benachrichtigt, wenn es soweit ist.
-(void)speechSynthesizer:(NSSpeechSynthesizer *)sender didFinishSpeaking:
     (
BOOL) finishedSpeaking
{
    [speakButton setEnabled:
TRUE];
    [silenceButton setEnabled:
FALSE];
}
Zum Abschluss noch einmal der gesamte Code im Überblick.

Die erweiterte MyController.h
#import <Cocoa/Cocoa.h>

@interface MyController : NSObject {

    NSSpeechSynthesizer *mySpeechSynth;
    IBOutlet NSTextField *inputTextField;
    IBOutlet NSButton *speakButton;
    IBOutlet NSButton *silenceButton;
}

-(
IBAction)speak:(id)sender;
-(
IBAction)silence:(id)sender;

@end
Und die Implementierung in der MyController.m
#import "MyController.h"

@implementation MyController

-(
void)awakeFromNib
{
    [silenceButton setEnabled:
FALSE];
    mySpeechSynth = [[NSSpeechSynthesizer alloc] initWithVoice:
nil];
    [mySpeechSynth setDelegate:
self];
}

- (
IBAction)speak:(id)sender
{
    [speakButton setEnabled:
FALSE];
    [silenceButton setEnabled:
TRUE];
    NSString *aText = [inputTextField stringValue];
    [mySpeechSynth startSpeakingString:aText];
}

- (
IBAction)silence:(id)sender
{
    [speakButton setEnabled:
TRUE];
    [silenceButton setEnabled:
FALSE];
    [mySpeechSynth stopSpeaking];
}

-(
void)speechSynthesizer:(NSSpeechSynthesizer *)sender didFinishSpeaking:
     (
BOOL) finishedSpeaking
{
    [speakButton setEnabled:
TRUE];
    [silenceButton setEnabled:
FALSE];
}

@end