NSView子类如何与控制器通信?

swi*_*ams 9 macos cocoa nsview

我是Cocoa编程的新品牌,我仍然对事物如何连接感到困惑.

我需要一个非常简单的应用程序,DoStuff只要点击窗口上的任何一点,它就会触发一个命令(让我们调用它).经过一些研究后,看起来子类化NSView是正确的方法.我的ClickerView.m文件有这个:

- (void)mouseDown:(NSEvent *)theEvent {
    NSLog(@"mouse down");
}
Run Code Online (Sandbox Code Playgroud)

我已经将视图添加到窗口并使其在整个事物中延伸,并且每次单击窗口时都正确地写入日志.

我的doStuff控制器上也有我的方法(这可以重构为我自己的类,但是现在它可以工作):

- (IBAction)doStuff:(id)sender {
    // do stuff here
}
Run Code Online (Sandbox Code Playgroud)

所以,我如何才能mouseDownClickerView能够调用DoStuff控制器?我有一个强大的.NET背景,有了这个,我只在ClickerView中有一个自定义事件,Controller会消耗; 我只是不知道如何在Cocoa中做到这一点.

根据Joshua Nozzi的建议编辑

IBOutlet在我的View中添加了一个(并将其更改为子类NSControl):

@interface ClickerView : NSControl {
    IBOutlet BoothController *controller;
}
@end
Run Code Online (Sandbox Code Playgroud)

我通过单击并从controllerView上的Outlets面板中的项目拖动到控制器,将控制器连接到它.我的mouseDown方法现在看起来像:

- (void)mouseDown:(NSEvent *)theEvent {
    NSLog(@"mouse down");
    [controller start:self];
}
Run Code Online (Sandbox Code Playgroud)

但是控制器没有实例化,调试器将其列为0x0,并且不发送消息.

iai*_*ain 13

您可以将其添加为像Joshua所说的IBOutlet,也可以使用委托模式.

您将创建一个描述委托方法的协议

@protocol MyViewDelegate
    - (void)doStuff:(NSEvent *)event;
@end
Run Code Online (Sandbox Code Playgroud)

然后你会让你的视图控制器符合MyViewDelegate协议

@interface MyViewController: NSViewController <MyViewDelegate> {
    // your other ivars etc would go here 
}
@end
Run Code Online (Sandbox Code Playgroud)

然后你需要提供doStuff的实现:在MyViewController的实现中:

- (void)doStuff:(NSEvent *)event
{
    NSLog(@"Do stuff delegate was called");
}
Run Code Online (Sandbox Code Playgroud)

然后在你的视图中,你将为代表添加一个弱属性.委托应该是弱的,这样就不会形成保留循环.

@interface MyView: NSView

@property (readwrite, weak) id<MyViewDelegate> delegate;

@end
Run Code Online (Sandbox Code Playgroud)

然后在你看来你会有类似的东西

- (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];
    }
 }
Run Code Online (Sandbox Code Playgroud)

最后:)每当您的视图控制器创建视图时,您需要设置委托

 ...
 MyView *view = [viewController view];
 [view setDelegate:viewController];
 ...
Run Code Online (Sandbox Code Playgroud)

现在,只要单击视图,就应该调用视图控制器中的委托.