我正在关注" Mac OS X"的Cocoa编程示例,它解释了如何为NSTableView实现协议。
我试图像书中所做的那样做,但可能我错过了一些东西
有一个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文件中完成了以下操作:
- 我已经连接了NSTableView的选项&#34;数据源&#34;和#34;委托&#34;到SpeakLineAppDelegate(我的应用程序的文件名)。
IBOutlet textField与xib文件中的NSTextField链接,同时说出和停止是为xib文件中的按钮设置的操作。
NSTableView是IBOutlet&#34; tableView&#34;,也是这个链接在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如果我在抛出异常时尝试打印行的值,它会打印为零,所以我真的不知道我的代码有什么问题。