-(void) mouseClicked() { if (target != nil && action != nil && [target respondsToSelector:action]) { [target performSelector:action withObject:self]; } } 下面我们通过具体的代码来展示一下这个技术。 #import <Cocoa/Cocoa.h> @interface MyController : NSObject { } - (void) onButtonClicked:(id)sender; @end @implementation MyController - (void) onButtonClicked:(id)sender { [NSApp terminate:NSApp]; } @end int main(int argc, char *argv[]) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; [NSApplication sharedApplication]; //Create main window NSRect rc = NSMakeRect(0, 0, 800, 600); NSUInteger uiStyle = NSTitledWindowMask | NSResizableWindowMask | NSClosableWindowMask; NSBackingStoreType backingStoreStyle = NSBackingStoreBuffered; NSWindow* win = [[NSWindow alloc] initWithContentRect:rc styleMask:uiStyle backing:backingStoreStyle defer:NO]; [win setTitle:@"HelloWin Test"]; //Create a button and set it as content view NSButton* button = [[NSButton alloc] initWithFrame:NSMakeRect(200, 200, 60, 40)]; [button setTitle:@"Quit Application"]; [win setContentView:button]; //Set target and action MyController* controller = [[MyController alloc] init]; [button setTarget:controller]; [button setAction:@selector(onButtonClicked:)]; [win center]; //Center main Window [win makeKeyAndOrderFront:win]; [win makeMainWindow]; [NSApp run]; [button release]; [win release]; [pool drain]; return 0; }
上面这段代码首先创建了一个窗口,然后在窗口内创建了一个Button,这个Button作为窗口的ContentView呈现,因为NSButton是从NSView继承来的,所以也是NSView的一个实例。在创建了Button对象之后,我们就为这个Button对象设置了用来处理缺省事件的Target对象,然后又通过setAction来设置处理这个事件的方法, 这里要注意的是这个Action方法一定是可以被Target响应的,也就是说符合respondsToSelector:的调用。
这个Target对象的实现被放在一个叫做MyController的类里面,它实现了一个方法叫做onButtonClicked:,这个方法被作为一个Action方法,所以它有一个参数(id)sender,这是因为Action方法被调用的时候,调用者会将触发这个Action的对象通过这个参数传递给Action方法。这个例子的实现很简单,直接调用NSApp对象的Terminate:方法来退出应用程序。
这个例子结束的地方和以前有所不同, 我分别调用了Button和Window的release方法,这是因为Window和Button对象都是通过引用形式分配的,所以当不再需要使用的时候需要将他们所占用的资源释放掉。Obj-C 2.0中提供了Garbage Colletion的功能,你分配的对象会在不被使用的时候自动释放,不过如果能了解Cocoa对象的分配和释放模式,对我们理解整个Cocoa框架的实现还是大有益处的。
上面这个例子还有一个地方需要注意的是Button的大小,你可以看到在代码中我为button分配的Rect的大小是60x40,但是运行的时候你会发现这个Button充满了整个Windows的Content区域,这是因为这个Button作为Window的ContentView,而Window的ContentView的Size Policy是随父窗口改变高度和宽度的。如果我们将
[win setContentView:button];
这句代码注释掉,换成下面的这句
[[win contentView] addSubview:button];
那么这个Button就在窗口中被正确定位了, 但是当你改变窗口大小的时候,这个Button的位置和大小都没有改变,这个是由它的Sizing Policy决定的。
原帖:http://www.cocoachina.com/bbs/read.php?tid=27&keyword=target|action