代码之家  ›  专栏  ›  技术社区  ›  erikprice

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

  •  3
  • erikprice  · 技术社区  · 16 年前

    这是一个CocoaN00B问题-我在其他环境中多年来一直在编程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 数组实例变量用作 画矩形 方法用于绘制形状。新的 NSRect S被添加到 形状 每次用户执行鼠标向下/拖动/鼠标向上顺序时,我也在这个自定义视图中实现了这一点。我的问题是:

    如果这是一个“真正的”Cocoa应用程序,那么定制视图更新其模型的惯用方法是什么?

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

    我的直觉是,惯用的可可代码会暴露 delegate 属性,然后连接 MyDocument 控制器对象(或文档控制器上挂起的另一个控制器层对象)作为其委托,放到XIB文件中的视图中。然后视图可以调用一些方法,比如 shapeAdded:(NSRect)shape 代表。但似乎有许多其他方法可以做到这一点,例如让控制器将对模型对象(形状列表)的引用直接传递到自定义视图(感觉错误),或者让视图发送控制器将要听取的通知(感觉不方便),然后控制器更新模型。

    3 回复  |  直到 16 年前
        1
  •  4
  •   Peter Hosey    16 年前

    有一个代表是 cromulent 这样做的方法。另一种方法是在视图上公开nsarray绑定,并将其绑定到数组控制器的 arrangedObjects 绑定,然后绑定数组控制器的 content 绑定到包含模型对象的实际数组的所有者。然后可以在同一阵列控制器上添加其他视图,例如活动层中的对象列表。

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

        2
  •  2
  •   Evan    16 年前

    在您的/developer/examples/appkit/sketch目录中有一个非常好的Xcode项目示例,它是您正在做的事情的一个更高级的版本,但是仍然是相关的。它有很多在控制器和视图之间使用绑定的例子,这将为正确的操作方式提供帮助。这个例子不使用ib插件,所以您将看到绑定的手动调用和实现的观察方法。

        3
  •  1
  •   cobbal    16 年前

    您的代码和一个不稳定视图之间有几个相似之处,所以我将研究使用数据源(类似于您的委托),甚至绑定。