在两个类中调用IBAction方法 [英] Call an IBAction method in two classes

查看:132
本文介绍了在两个类中调用IBAction方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在两个类中调用IBAction方法,每当我在界面构建器中创建的按钮被点击时调用。我真正想要发生的是一个NSRect出现每当按钮被点击,但按钮和我想要NSRect出现的地方在不同的视图,所以按钮是在视图A和目标的rect是在

解决方案

您已经失去了 C 中的 MVC 。 Cocoa使用 Model-View- Controller 设计模式,您似乎缺少一个控制器。



创建一个控制器类(可能是 NSWindowController 的子类,以便它负责窗口)实现一个动作方法,例如 -buttonPressed: code>这是连接到你的按钮。控制器应该管理模型(在这种情况下是任何矩形表示),以便当您按下按钮时,模型被更新。



您的矩形视图应该设置为实现一个数据源模式(参见 NSTableView datasource实现一个很好的例子),使它知道有多少和在哪里绘制矩形。如果将控制器设置为视图的数据源,则视图不需要知道模型的任何内容。



您的矩形视图应该设置为这样: / p>

RectangleView.h:
@protocol RectangleViewDataSource;

  @interface RectangleView:NSView 
@property(weak)id< RectangleViewDataSource>数据源;
@end

//这是提供视图的数据源协议
@protocol RectangleViewDataSource< NSObject>
- (NSUInteger)numberOfRectsInView:(RectangleView *)view;
- (NSRect)rectangleView:(RectangleView *)view rectAtIndex:(NSUInteger)anIndex;
@end

RectangleView.m:

  @implementation RectangleView 
@synthesize dataSource;

- (void)drawRect:(NSRect)rect
{
//只有当我们有一个数据源时才会显示
if([dataSource conformsToProtocol:@protocol RectangleViewDataSource)])
{
//从控制器获取rect数量
NSUInteger numRects = [dataSource numberOfRectsInView:self];
for(NSUInteger i = 0; i {
NSRect currentRect = [dataSource rectangleView:self rectAtIndex:i];
//绘制矩形
NSFrameRect(currentRect);
}
}
}
@end

您可以将控制器分配为视图的数据源,并使其实现 RectangleViewDataSource 协议方法。



看起来像这样:



YourController.h

  #importRectangleView.h

@interface YourController:NSWindowController< RectangleViewDataSource>
@property(strong)NSMutableArray * rects;
@property(strong)IBOutlet RectangleView * rectView;

- (IBAction)buttonPressed:(id)sender;

@end

YourController.m

  @implementation YourController 
@synthesize rects;
@synthesize rectView;

- (id)init
{
self = [super init];
if(self)
{
rects = [[NSMutableArray alloc] init];
}
return self;
}


- (void)awakeFromNib
{
//将此控制器分配为视图的数据源
self.rectView.dataSource = self;
}

- (IBAction)buttonPressed:(id)sender
{
NSRect rect = NSMakeRect(0,0,100,100); // create rect here
[rects addObject:[NSValue valueWithRect:rect]];
[self.rectView setNeedsDisplay:YES];
}

// RectangleViewDataSource方法
- (NSUInteger)numberOfRectsInView:(RectangleView *)view
{
return [rects count]
}

- (NSRect)rectangleView:(RectangleView *)view rectAtIndex:(NSUInteger)anIndex
{
return [[rects objectAtIndex:anIndex] rectValue];
}


@end


Im trying to call an IBAction Method in two classes that is called whenever a button that I created in interface builder is clicked. What I really want to happen is for a NSRect to appear whenever the button is clicked but the button and the place where I want the NSRect to appear are in separate views, so the button is in View A and the destination for the rect is in View B. I have tried doing this with NSNotificationCenter but it did not work.

解决方案

You are missing the C in MVC. Cocoa uses the Model-View-Controller design pattern and you seem to be missing a controller.

You should create a controller class (possibly a subclass of NSWindowController so that it is responsible for the window) that implements an action method such as -buttonPressed: which is connected to your button. The controller should manage the model (which in this case is whatever the rectangles represent) such that when you press the button, the model is updated. The controller should then make your rectangle view redraw itself.

Your rectangle view should be set up so that it implements a datasource pattern (see the NSTableView datasource implementation for a good example) so that it knows how many and where to draw the rectangles. If you set your controller as the view's datasource, your view doesn't need to know anything about the model.

Your rectangle view should be set up something like this:

RectangleView.h: @protocol RectangleViewDataSource;

@interface RectangleView : NSView
@property (weak) id <RectangleViewDataSource> dataSource;
@end

//this is the data source protocol that feeds the view
@protocol RectangleViewDataSource <NSObject>
- (NSUInteger)numberOfRectsInView:(RectangleView*)view;
- (NSRect)rectangleView:(RectangleView*)view rectAtIndex:(NSUInteger)anIndex;
@end

RectangleView.m:

@implementation RectangleView
@synthesize dataSource;

- (void)drawRect:(NSRect)rect
{
    //only draw if we have a data source
    if([dataSource conformsToProtocol:@protocol(RectangleViewDataSource)])
    {
        //get the number of rects from the controller
        NSUInteger numRects = [dataSource numberOfRectsInView:self];
        for(NSUInteger i = 0; i < numRects; i++)
        {
            NSRect currentRect = [dataSource rectangleView:self rectAtIndex:i];
            //draw the rect
            NSFrameRect(currentRect);
        }
    }
}
@end

You would assign your controller as the datasource of the view and make it implement the RectangleViewDataSource protocol methods.

The controller would look something like this:

YourController.h:

#import "RectangleView.h"

@interface YourController : NSWindowController <RectangleViewDataSource>
@property (strong) NSMutableArray* rects;
@property (strong) IBOutlet RectangleView *rectView;

- (IBAction)buttonPressed:(id)sender;

@end

YourController.m:

@implementation YourController
@synthesize rects;
@synthesize rectView;

- (id)init 
{
    self = [super init];
    if (self) 
    {
        rects = [[NSMutableArray alloc] init];
    }
    return self;
}


- (void)awakeFromNib
{
    //assign this controller as the view's data source
    self.rectView.dataSource = self;
}

- (IBAction)buttonPressed:(id)sender
{
    NSRect rect = NSMakeRect(0,0,100,100); //create rect here
    [rects addObject:[NSValue valueWithRect:rect]];
    [self.rectView setNeedsDisplay:YES];
}

//RectangleViewDataSource methods
- (NSUInteger)numberOfRectsInView:(RectangleView*)view
{
    return [rects count];
}

- (NSRect)rectangleView:(RectangleView*)view rectAtIndex:(NSUInteger)anIndex
{
    return [[rects objectAtIndex:anIndex] rectValue];
}


@end

这篇关于在两个类中调用IBAction方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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