我遇到了MVC主要概念的问题。我认为我知道应该链接和发生什么,但我有一个基本的MVC问题。
"项目"
用户在视图(MVCView.h/m)
上绘制形状的基本应用程序。当他拖动鼠标时,将在视图上绘制形状。但我还希望在MVCViewController.h/m
NSMutableArray* shapeArray
中添加形状。然后,ViewController将使用MVCModel
MVCView
类
问题
我不知道如何调用这些函数(参见下面的代码和/或项目),因为"他们"总是说你永远不能直接从视图中调用模型类。因为这是我以前的做法。 (视图类中有NSMutableArray
)
所以,请帮助我。我喜欢理解语法/概念!
本
在此处下载项目:(谷歌驱动器) MVC Controller Project
代码: MVCViewController.h:
#import <Cocoa/Cocoa.h>
#import "MVCModel.h"
@interface MVCViewController : NSViewController
{
//Array to save the shapes to
NSMutableArray* shapeArray;
}
-(void)addShapeWithBeginPoint:(NSPoint)beginPoint andEndPoint:(NSPoint)endPoint withColor:(NSColor*)fillColor;
-(NSInteger)countItemsInArray;
@end
MVCViewController.m:
#import "MVCViewController.h"
@interface MVCViewController ()
@end
@implementation MVCViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
//Create array when view is loaded.
shapeArray = [[NSMutableArray alloc]init];
}
return self;
}
-(void)addShapeWithBeginPoint:(NSPoint)beginPoint andEndPoint:(NSPoint)endPoint withColor:(NSColor*)fillColor
{
//Add the model to the MVCViewController Array!
MVCModel *shape = [[MVCModel alloc]initWithName:[NSString stringWithFormat:@"Shape: %d",(int)[self countItemsInArray]] atBeginPoint:beginPoint endAt:endPoint fillWithColor:fillColor];
[shapeArray addObject:shape];
//In the Future
//In the near future some other shapes like circles, lines, arrows etc have to be added using tags from a PopUpButton.
//Also the color has to be set to the NSColorPicker Color.
//In the Future
}
-(NSInteger)countItemsInArray{
//Count the amount of items in array
NSLog(@"%d",(int)shapeArray.count);
return [shapeArray count];
}
@end
MVCModel.h:
#import <Foundation/Foundation.h>
@interface MVCModel : NSObject
{
NSString* name;
NSPoint beginPoint;
NSPoint endPoint;
NSColor* fillColor;
}
-(id)initWithName:(NSString*)name atBeginPoint:(NSPoint)beginPoint endAt:(NSPoint)endPoint fillWithColor:(NSColor*)fillColor;
@end
MVCModel.m:
#import "MVCModel.h"
@implementation MVCModel
//Every shape has these variables.
-(id)initWithName:(NSString*)newName atBeginPoint:(NSPoint)newBeginPoint endAt:(NSPoint)newEndPoint fillWithColor:(NSColor*)newFillColor{
self = [super init];
if(self)
{
name = newName;
beginPoint = newBeginPoint;
endPoint = newEndPoint;
fillColor = newFillColor;
}
return self;
}
@end
MVCView.h:
#import <Cocoa/Cocoa.h>
@interface MVCView : NSView{
NSPoint cursorStartPoint;
NSPoint cursorEndPoint;
NSSize size;
}
@end
MVCView.m:
#import "MVCView.h"
@implementation MVCView
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code here.
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect
{
[super drawRect:dirtyRect];
//drawing the shape when the user clicks.
[[NSColor gridColor]set];
NSBezierPath *path = [NSBezierPath bezierPathWithRect:NSMakeRect(cursorStartPoint.x,
cursorStartPoint.y,
size.width,
size.height)];
[path stroke];
//drawing all the Shapes to the view
// So the code I think of should be:
/*
for(MVCModel* shape in shape.array)
{
NSBezierPath* path = [NSBezierPath bezierPathWithRect:[NSMakeRect(shape.beginPoint.x,shape.beginPoint.y,shape.endPoint.x, shape.endPoint.y)]]
}
BUT as MVC states, the view can never "talk" to the data model which it does here. So Do I make an instance of it?
How will it work?
*/
}
-(void)mouseDown:(NSEvent *)theEvent
{
//Get the clicked value from the cursor in the view
NSLog(@"Mouse Clicked");
cursorStartPoint = [self convertPoint:[theEvent locationInWindow]fromView:nil];
}
-(void)mouseDragged:(NSEvent *)theEvent
{
//get the last cursorvalue from the cursor in the view
//Set needs display to draw something so the user can see it.
NSLog(@"Mouse Dragged");
cursorEndPoint = [self convertPoint:[theEvent locationInWindow]fromView:nil];
size.width = cursorEndPoint.x - cursorStartPoint.x;
size.height = cursorEndPoint.y - cursorStartPoint.y;
[self setNeedsDisplay:YES];
}
-(void)mouseUp:(NSEvent *)theEvent
{
/*Call MVCViewController to call:
-(void)addShapeWithBeginPoint:(NSPoint)beginPoint andEndPoint:(NSPoint)endPoint withColor:(NSColor*)fillColor
So the data model to init itself and send itself back to the controller to add itself to the shapeArray in MVCViewController
To eventually call the DrawRect: Method in MVCView(self) to draw itself with the function:
[self SetNeedsDisplay:YES];
*/
}
@end
答案 0 :(得分:0)
“他们”说你不应该直接从视图中调用模型类。 但话虽如此,当我们需要视图让模型知道事件已经发生并且需要更新模型数据时,这是一个常见问题。
为此,您创建一个名为NSNotifications的无线电广播,并且viewController调整到事件的广播中。在此广播中,您发送事件的元数据,然后对数据库中收到的数据执行操作。 基本上,我们从不调用从视图中改变模型的方法,我们只是调入视图中的事件,让控制器调用方法。您还可以设置特定视图或控制器的委托以代表其执行操作(即更新模型)。
http://nshipster.com/nsnotification-and-nsnotificationcenter/
对不起,我没有给出你问题的具体答案,但这是我用来处理查看事件和更新模型的一般方法。