自定义视图应如何更新模型对象?

eri*_*ice 3 architecture cocoa idioms

这是一个可可n00b问题-我已经在其他环境中对GUI应用程序进行了多年编程,但是现在我想了解在以下琐碎情况下什么是“惯用可可”:

我有一个简单的自定义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]];
}
Run Code Online (Sandbox Code Playgroud)

您可以看到这段代码很简单:shapes数组实例变量充当该drawRect方法用来绘制形状的模型。每当用户执行鼠标向下/拖动/鼠标向上顺序时,都会NSRect添加新的shapes,我也已在此自定义视图中实现了该顺序。这是我的问题:

如果这是一个“真实”的Cocoa应用程序,我的自定义视图更新其模型的惯用方式是什么?

换句话说,自定义视图应如何通知控制器需要将另一个形状添加到形状列表中?现在,该视图以其自身的形式跟踪形状NSMutableArray,这可以很好地实现,但我不想将此数组作为自定义视图的公共API的一部分公开。此外,我想将错误检查,保存/加载和撤消代码放在控制器之类的集中位置,而不是在我的自定义视图中乱七八糟。根据我过去在其他GUI编程环境中的经验,模型是由我的控制器层中的一个对象管理的,视图通常不会直接更新它们-而是,当事情发生时,视图通过调度事件或调用a进行通信。控制器上引用的方法或使用类似解耦的方法。

我的直觉是,惯用的Cocoa代码会delegate在我的自定义视图上公开一个属性,然后将MyDocument控制器对象(或挂在文档控制器上的另一个控制器层对象)连接到xib文件中的视图作为其委托。然后,视图可以调用某些方法,例如shapeAdded:(NSRect)shape委托。但是似乎还有许多其他方法可以执行此操作,例如让控制器将对模型对象的引用(形状列表)直接传递给自定义视图(感觉不对),或者让视图分派通知控制器将收听(感觉很笨拙),然后控制器更新模型。

Pet*_*sey 5

拥有代表是这样做的一种繁琐方式。另一种方法是在视图上公开NSArray绑定,并将其绑定到数组控制器的arrangedObjects绑定,然后将数组控制器的content绑定绑定到拥有模型对象的真实数组的任何对象。然后,您可以在同一阵列控制器上添加其他视图,例如活动层中的对象列表。

这是一个自定义视图,您需要创建一个IBPlugin以在IB中公开绑定,或者通过向该视图发送bind:toObject:withKeyPath:options:消息以编程方式绑定它。