这是一个 Cocoa n00b 问题 - 我多年来一直在其他环境中编写 GUI 应用程序,但现在我想了解以下琐碎情况下的“惯用 Cocoa”是什么:
我有一个简单的自定义NSView
,允许用户在其中绘制简单的形状。它的drawRect
实现是这样的:
- (void)drawRect:(NSRect)rect
{
// Draw a white background.
[[NSColor whiteColor] set];
NSRect bounds = [self bounds];
[NSBezierPath fillRect:bounds];
[[NSColor blackColor] set];
// 'shapes' is a NSMutableArray instance variable
// whose elements are NSValues, each wrapping an NSRect.
for (NSValue *value in shapes)
{
NSRect someRect;
[value getValue:&someRect];
[self drawShapeForRect:someRect];
}
// In addition to drawing the shapes in the 'shapes'
// array, we draw the shape based on the user's
// current drag interaction.
[self drawShapeForRect:[self dragRect]];
}
您可以看到这段代码是多么简单:shapes
数组实例变量充当该drawRect
方法用来绘制形状的模型。每次用户执行鼠标向下/拖动/鼠标向上序列时都会NSRect
添加新的 s,我也在这个自定义视图中实现了这一点。shapes
这是我的问题:
如果这是一个“真正的”Cocoa 应用程序,我的自定义视图更新其模型的惯用方式是什么?
换句话说,自定义视图应该如何通知控制器需要将另一个形状添加到形状列表中?现在,视图在其自身中跟踪形状NSMutableArray
,这作为实现细节很好,但我不想将此数组公开为我的自定义视图的公共 API 的一部分。此外,我希望将错误检查、保存/加载和撤消代码放在像控制器这样的集中位置,而不是让它散落在我的自定义视图中。在我过去使用其他 GUI 编程环境的经验中,模型由我的控制器层中的对象管理,并且视图通常不会直接更新它们 - 相反,视图在发生某些事情时进行通信,通过调度事件或调用它引用的控制器上的方法,或使用一些类似的解耦方法。
我的直觉是,惯用的 Cocoa 代码会delegate
在我的自定义视图上公开一个属性,然后将MyDocument
控制器对象(或挂在文档控制器之外的另一个控制器层对象)连接到 xib 文件中的视图,作为其委托。然后视图可以调用一些方法,比如shapeAdded:(NSRect)shape
委托。但似乎还有许多其他方法可以做到这一点,例如让控制器将模型对象(形状列表)的引用直接传递给自定义视图(感觉不对),或者让视图发送通知控制器会听(感觉笨拙),然后控制器更新模型。