我是Cocoa编程的新品牌,我仍然对事物如何连接感到困惑。
我需要一个非常简单的应用程序,只要点击窗口上的任何一个点,它就会触发一个命令(让我们称之为DoStuff
)。经过一些研究后,看起来像NSView
的子类化是正确的方法。我的ClickerView.m
文件有这个:
- (void)mouseDown:(NSEvent *)theEvent {
NSLog(@"mouse down");
}
我已经将视图添加到窗口并使其在整个事物中延伸,并且每次单击窗口时都正确地写入日志。
我的控制器上也有我的doStuff
方法(这可以重构为我自己的类,但是现在它可以工作):
- (IBAction)doStuff:(id)sender {
// do stuff here
}
那么,如何让mouseDown
中的ClickerView
能够在控制器中调用DoStuff
?我有一个强大的.NET背景,有了这个,我只在ClickerView中有一个自定义事件,Controller会消耗掉;我只是不知道如何在Cocoa中做到这一点。
根据Joshua Nozzi的建议编辑
我在我的View中添加了一个IBOutlet
(并将其更改为子类NSControl
):
@interface ClickerView : NSControl {
IBOutlet BoothController *controller;
}
@end
我通过单击并从View上Outlets面板中的controller
项目拖动到控制器,将控制器连接到它。我的mouseDown
方法现在看起来像:
- (void)mouseDown:(NSEvent *)theEvent {
NSLog(@"mouse down");
[controller start:self];
}
但是控制器没有实例化,调试器将其列为0x0,并且不发送消息。
您可以将其添加为像Joshua所说的IBOutlet,也可以使用委托模式。
您将创建一个描述委托方法的协议
@protocol MyViewDelegate
- (void)doStuff:(NSEvent *)event;
@end
然后你会让你的视图控制器符合MyViewDelegate协议
@interface MyViewController: NSViewController <MyViewDelegate> {
// your other ivars etc would go here
}
@end
然后你需要提供doStuff的实现:在MyViewController的实现中:
- (void)doStuff:(NSEvent *)event
{
NSLog(@"Do stuff delegate was called");
}
然后在你的视图中,你将为代表添加一个弱属性。委托应该是弱的,这样就不会形成保留循环。
@interface MyView: NSView
@property (readwrite, weak) id<MyViewDelegate> delegate;
@end
然后在你看来你会有类似的东西
- (void)mouseDown:(NSEvent *)event
{
// Do whatever you need to do
// Check that the delegate has been set, and this it implements the doStuff: message
if (delegate && [delegate respondsToSelector:@selector(doStuff:)]) {
[delegate doStuff:event];
}
}
最后:)每当您的视图控制器创建视图时,您需要设置委托
...
MyView *view = [viewController view];
[view setDelegate:viewController];
...
现在,只要单击视图,就应该调用视图控制器中的委托。
首先,您的视图需要引用控制器。这可以是在运行时设置的简单iVar或在设计时连接的插座(由IBOutlet指定)。
其次,NSControl是NSView的子类,它免费提供target/action机制机制。用于目标/动作样式控件。这提供了一种设置对控制器(目标)的引用和触发时调用的方法(操作)的简单方法。即使你不使用单元格,你仍然可以轻松地使用目标/动作(NSControl通常只是将这些东西转发到它的NSCell子类的实例,但不必)。
您还可以使用选择器调用方法,在自定义类中定义两个属性:
@property id parent;
@property SEL selector;
在视图控制器中设置它们:
graph.selector=@selector(onCalcRate:);
graph.parent=self;
并称为:
-(void)mouseDown:(NSEvent *)theEvent {
[super mouseDown:theEvent];
[_parent performSelector:_selector withObject:self];
}