0

NSTableView のプロトコルを実装する方法を説明する「Mac OS X の Cocoa プログラミング」の例に従っています。
私は本に書かれているようにすべてをやろうとしましたが、おそらく何かを見逃しています.
NSSpeechSynthesizer とテキスト フィールドがあり、ユーザーが「話す」ボタンを押すたびに、テキスト フィールドの内容が音声シンセサイザーによって読み上げられます。すべての音声のリストを含む NSTableView もあり、ユーザーはもっと好きだという声。
これはコードです:

インターフェース:

#import <Cocoa/Cocoa.h>

@interface SpeakLineAppDelegate : NSObject <NSApplicationDelegate, NSSpeechSynthesizerDelegate, NSTableViewDelegate, NSTableViewDataSource> 
{
@private
    NSWindow *window;
    NSTextField *textField;
    NSTableView *tableView;
    NSButton *speakButton;
    NSSpeechSynthesizer* ss;
    NSButtonCell *stopButton;
    NSArray* voices;
}

@property (assign) IBOutlet NSWindow *window;
@property (assign) IBOutlet NSTextField *textField;
@property (assign) IBOutlet NSTableView *tableView;

@property (assign) IBOutlet NSButton *speakButton;

- (IBAction)speak:(id)sender;
- (IBAction)stop:(id)sender;
@property (assign) IBOutlet NSButtonCell *stopButton;


@end

実装:

#import "SpeakLineAppDelegate.h"

@implementation SpeakLineAppDelegate
@synthesize stopButton;
@synthesize textField;
@synthesize tableView;
@synthesize speakButton;

@synthesize window;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    // Insert code here to initialize your application
 }


- (id) init
{
    self=[super init];
    if(self)
    {
        NSLog(@"init method called");
        ss=[[NSSpeechSynthesizer alloc]initWithVoice:nil];
        [ss setDelegate: self];
        voices=[NSSpeechSynthesizer availableVoices];
    }
    return self;
}

- (IBAction)speak:(id)sender 
{
    NSString* str=[textField stringValue];
    if([str length]>0)
    {
        [ss startSpeakingString: str];
        [stopButton setEnabled: YES];
        [speakButton setEnabled: NO];
    }
    else
    {
        NSLog(@"The string has length zero");
    }
}

- (IBAction)stop:(id)sender 
{
    [ss stopSpeaking];
}

- (void) speechSynthesizer:(NSSpeechSynthesizer *)sender didFinishSpeaking:   (BOOL)finishedSpeaking
{
    NSLog(@"Has finished speaking");
    [stopButton setEnabled: NO];
    [speakButton setEnabled: YES];
}

- (NSInteger) numberOfRowsInTableView:(NSTableView *)tableView
{
    return [voices count];
}

- (id) tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
    NSString* str=[voices objectAtIndex: row];
    NSDictionary* dict=[NSSpeechSynthesizer attributesForVoice: str];
    return [dict objectForKey: NSVoiceName];
}


- (void)tableViewSelectionDidChange:(NSNotification *)notification
{
    NSInteger row=[tableView selectedRow];
    if(row!=-1)
    {
        NSString* str=[voices objectAtIndex: row];
        [ss setVoice: str];
        NSLog(@"New voice: %@",str);
    }
}

@end

また、xib ファイルで次のことを行いました

IBOutlet textField は、xib ファイルの NSTextField とリンクされています。また、話すと停止は、xib ファイルのボタンに設定されたアクションです。
NSTableView は IBOutlet の「tableView」であり、これも xib ファイルにリンクされています。
問題: この時点で EXC_BAD_ACCESS を取得します。

- (id) tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
    NSString* str=[voices objectAtIndex: row];  // here I get the exception
    NSDictionary* dict=[NSSpeechSynthesizer attributesForVoice: str];
    return [dict objectForKey: NSVoiceName];
}

ボイスは init メソッドで割り当てられるため、この例外の理由がわかりません。
gdb では、例外がスローされたときに行の値を出力しようとすると、ゼロが出力されるため、コードの何が問題なのか本当にわかりません。

4

0 に答える 0