NSView子类如何与控制器通信? [英] How does an NSView subclass communicate with the controller?

查看:108
本文介绍了NSView子类如何与控制器通信?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Cocoa编程的新手,对事物如何组合仍然感到困惑.

I am brand spanking new to Cocoa programming, and am still kind of confused about how things wire together.

我需要一个非常简单的应用程序,该应用程序将在单击窗口的任何点时触发一个命令(将其称为DoStuff).经过一番研究,似乎将NSView子类化是正确的方法.我的ClickerView.m文件具有以下内容:

I need a pretty simple application that will fire off a single command (let's call it DoStuff) whenever any point on the window is clicked. After a bit of research it looks like subclassing NSView is the right way to go. My ClickerView.m file has this:

- (void)mouseDown:(NSEvent *)theEvent {
    NSLog(@"mouse down");
}

并且我已经将View添加到Window,并使其延伸到整个对象,并且每次单击窗口时都正确地写入了日志.

And I have added the View to the Window and have it stretching across the whole thing, and is properly writing to the log every time the window is clicked.

我的控制器上也有我的doStuff方法(我想可以将其重构为自己的类,但目前可以使用):

I also have my doStuff method on my controller (this could be refactored to its own class I suppose, but for now it works):

- (IBAction)doStuff:(id)sender {
    // do stuff here
}

那么,如何在ClickerView中获得mouseDown以便能够在控制器中调用DoStuff?我有一个强大的.NET背景,因此,我会在ClickerView中有一个Controller会消耗的自定义事件;我只是不知道如何在可可粉中做到这一点.

So, how do I get mouseDown in ClickerView to be able to call DoStuff in the controller? I have a strong .NET background and with that, I'd just have a custom event in the ClickerView that the Controller would consume; I just don't know how to do that in Cocoa.

根据Joshua Nozzi的建议进行编辑

我在视图中添加了IBOutlet(并将其更改为子类NSControl):

I added an IBOutlet to my View (and changed it to subclass NSControl):

@interface ClickerView : NSControl {
    IBOutlet BoothController *controller;
}
@end

我通过单击视图的插座"面板中的controller项并将其拖动到控制器上,将控制器连接到该控制器.我的mouseDown方法现在看起来像:

I wired my controller to it by clicking and dragging from the controller item in the Outlets panel on the View to the controller. My mouseDown method now looks like:

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

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

But the controller isn't instantiated, the debugger lists it as 0x0, and the message isn't sent.

推荐答案

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

You could either add it as an IBOutlet like Joshua said, or you could use the delegate pattern.

您将创建一个协议,该协议描述您的委托人的方法,例如

You would create a Protocol that describes your delegate's methods like

@protocol MyViewDelegate
    - (void)doStuff:(NSEvent *)event;
@end

然后使您的视图控制器符合MyViewDelegate协议

then you'd make your view controller conform to the MyViewDelegate protocol

@interface MyViewController: NSViewController <MyViewDelegate> {
    // your other ivars etc would go here 
}
@end

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

Then you need to provide the implementation of the doStuff: in the implementation of MyViewController:

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

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

then in your view you'd add a weak property for the delegate. The delegate should be weak, so that a retain loop doesn't form.

@interface MyView: NSView

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

@end

然后在您看来,您会遇到类似的情况

and then in your view you'd have something like this

- (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];
    }
 }

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

and finally :) whenever your view controller creates the view, you need to set the delegate

 ...
 MyView *view = [viewController view];
 [view setDelegate:viewController];
 ...

现在,每当单击您的视图时,都应调用视图控制器中的委托.

Now whenever your view is clicked, the delegate in your view controller should be called.

这篇关于NSView子类如何与控制器通信?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆