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 では、例外がスローされたときに行の値を出力しようとすると、ゼロが出力されるため、コードの何が問題なのか本当にわかりません。