Objective-C/Cocoa/XCode 新手:如何接收通知?

Posted

技术标签:

【中文标题】Objective-C/Cocoa/XCode 新手:如何接收通知?【英文标题】:Objective-C/Cocoa/XCode Newbie: How to receive Notifications? 【发布时间】:2013-04-15 20:03:36 【问题描述】:

我无法从可可编程书​​中获得一个示例来工作(我认为部分问题是 XCode 已过时)。除了在 IB 中建立适当的连接之外,它没有提到我必须做任何特别的事情来接收来自 NSTableView 的通知。该应用程序是一个带有用于用户输入的 NSTextField 的程序,当单击按钮时,NSSpeechSynthesizer 的一个实例将说出输入的行。我应该能够通过在表格视图上选择一行来切换说话的声音。我可以点击,该应用在技术上可以正常工作,但我无法通过点击 GUI 上 NSTableView 上的一行来更改默认语音:

appdelegate.h:

#import <Cocoa/Cocoa.h>

@interface AppDelegate : NSObject <NSApplicationDelegate,NSSpeechSynthesizerDelegate,NSTableViewDelegate>

    NSArray *_voices;
    NSSpeechSynthesizer *_speechSynth;


@property (assign) IBOutlet NSWindow *window;
@property (weak) IBOutlet NSTextField *textField;
@property (assign) IBOutlet NSTextField *text;

@property (assign) IBOutlet NSButton *_speakButton;
@property (assign) IBOutlet NSButton *_stopButton;

@property (assign) IBOutlet NSTableView *table;

-(IBAction)sayIt:(id)sender;
-(IBAction)stopIt:(id)sender;

@end

appdelegate.m:

#import "AppDelegate.h"

@implementation AppDelegate

@synthesize window = _window;
@synthesize textField = _textField;
@synthesize text = _text;
@synthesize _speakButton;
@synthesize _stopButton;

@synthesize table;

-(void)speechSynthesizer:(NSSpeechSynthesizer *)sender didFinishSpeaking:(BOOL)finishedSpeaking

    NSLog(@"finishedSpeaking=%d",finishedSpeaking);
    [_speakButton setEnabled:YES];
    [_stopButton setEnabled:NO];
    [table setEnabled:YES];


-(id)init

    NSLog(@"init called");
    self = [super init];
    if (self)
    
        NSLog(@"init");
        _speechSynth = [[NSSpeechSynthesizer  alloc] initWithVoice:nil];
        [_speechSynth setDelegate:self];
        [_text setStringValue:@""];
        _voices = [NSSpeechSynthesizer availableVoices];
    

    //I added this line myself as I was trying to figure it out
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tableViewSelectionDidChange:) name:@"MyNotification" object:table];
    return self;

-(IBAction)sayIt:(id)sender

    NSString *string = [_textField stringValue];
    if([string length]==0)
    
        NSLog(@"string from %@ is of zero-length",_textField);
        return;
    
    [_speechSynth startSpeakingString:string];
    [_text setStringValue:[_speechSynth voice]];
    ...

-(IBAction)stopIt:(id)sender

    NSLog(@"stopping");
    ...

-(NSInteger)numberOfRowsInTableView:(NSTableView *)tv

    return (NSInteger)[_voices count];

-(id)tableView:(NSTableView *)tv
objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row

    NSString *v = [_voices objectAtIndex:row];
    NSDictionary *dict =[NSSpeechSynthesizer attributesForVoice:v];
    return [dict objectForKey:NSVoiceName];


-(void)tableViewSelectionDidChange:(NSNotification *)notification

    NSInteger row = [table selectedRow];
    if(row==-1) return;
    NSString *selectedVoice = [_voices objectAtIndex:row];
    [_speechSynth setVoice:selectedVoice];
    NSLog(@"new voice = %@",selectedVoice);


-(void)awakeFromNib

    NSLog(@"awakeFromNib");
    NSString *defaultVoice = [NSSpeechSynthesizer defaultVoice];
    NSInteger defaultRow = [_voices indexOfObject:defaultVoice];
    NSIndexSet *indices = [NSIndexSet indexSetWithIndex:defaultRow];
    [table selectRowIndexes:indices byExtendingSelection:NO];
    [table scrollRowToVisible:defaultRow];

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification

    NSLog(@"Appdidfinishlaunching called");


@end

我猜我弄错了。我只需要有人指出我应该如何工作的正确方向。

【问题讨论】:

什么不起作用?在我看来它工作得很好。您正在选择 Alex,文本字段显示 com.apple.speech.synthesis.voice.Alex。所以它会响应您的点击。究竟是什么问题? 哎呀。我的意思是说 appdelegate 没有通过点击 NSTableView 来更改默认的语音选择。 但它显然是,因为屏幕显示它是。该程序似乎运行良好。它可能没有做您期望它要做的事情,但它正在做它编写要做的事情。 有道理。所以我想我的问题是,我该如何做我想做的事?好,等一下。你认为是因为它说 blah.alex 它响应了点击。但 Alex 是默认语音,当程序启动时,Alex 默认会突出显示。但是当我点击 Bad News 或 Agnes 时,它仍然会说 Alex,因为即使我点击了那一行,声音也没有改变。文本字段告诉我正在使用哪个声音,而不是选择。 在这种情况下,您的屏幕截图不是一个很好的屏幕截图! 【参考方案1】:

这里有几个可能的错误来源。

您可能忘记将 nib 中的表格视图作为其 delegate 挂接到应用委托。

您可能忘记将 nib 中的应用代理挂接到文本字段,作为其 textField

(还有其他可能性(与在笔尖上连接东西有关)但我不会一一列举...)

如果您的目标确实是获取选择消息作为通知,那么这行是错误的:

[[NSNotificationCenter defaultCenter] 
  addObserver:self selector:@selector(tableViewSelectionDidChange:) 
  name:@"MyNotification" object:table];

此通知的名称不是@"MyNotification";是NSTableViewSelectionDidChangeNotification

【讨论】:

是的,但第一个是最有可能的。无需将此消息作为通知获取,因为您可以将其作为委托消息获取。小心你不会得到两次!

以上是关于Objective-C/Cocoa/XCode 新手:如何接收通知?的主要内容,如果未能解决你的问题,请参考以下文章

新随笔新随笔

笔新新随随笔 新随

Java16的新特性

sh 创建新分区,创建新文件系统,安装新磁盘

制作新按钮,“新窗口打开网站” ,点击打开新窗口。

制作新按钮,“新窗口打开网站” ,点击打开新窗口。