target action版简化命令设计模式原理分析
我们知道在Cocoa程序中, 如果你想处理一个窗口的事件或者应用程序的事件, 你可以使用Delegate的方法来实现响应的事件处理函数,但是如果你要处理一个button控件或者一个窗口里面很多的类似Button的这种有一种缺省行为的控件的时候, 是不是要为他们每个控件都来实现这个Delegate呢?答案是否定的,因为针对这些具有指定的缺省行为的控件,NSControl已经帮我们进行了一部分的处理(这个control要求继承自NSActionCell, 比如你添加一个Button到窗口中,那么对Button的Click事件,NSControl是有自己的处理的,这就是Target-Action模式,当Button的click事件被触发是,NSControl就会去检查这个Control中是否有对应的Target,这个Target针对这个事件处理的Action是什么,如果Target和Action都存在,那么这个Click事件就会被NSControl直接处理,类似的处理代码如下(假设的实现)
-(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; }
[win setContentView:button];
[[win contentView] addSubview:button];