Как пользовательский вид должен обновлять объект модели? - PullRequest
3 голосов
/ 25 марта 2009

Это вопрос Cocoa n00b - я годами программировал приложения с графическим интерфейсом в других средах, но теперь я хотел бы понять, что такое «идиоматическое Какао» для следующей тривиализированной ситуации:

У меня есть простой пользовательский 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 каждый раз, когда пользователь выполняет последовательность мыши-перетаскивания / перетаскивания / мыши-вверх, которую я также реализовал в этом пользовательском представлении. Вот мой вопрос:

Если бы это было "настоящее" приложение Какао, какой бы идиоматический способ был для моего пользовательского представления обновить его модель?

Другими словами, как пользовательский вид должен уведомлять контроллер о необходимости добавления другой фигуры в список фигур? Прямо сейчас, представление отслеживает формы в своем собственном NSMutableArray, что хорошо в качестве детали реализации, но я не хочу показывать этот массив как часть открытого API моего пользовательского представления. Кроме того, я хотел бы поместить код проверки ошибок, сохранения / загрузки и отмены кода в централизованное место, например, контроллер, а не засорять его во всех моих пользовательских представлениях. В моем прошлом опыте работы с другими средами программирования графического интерфейса модели управляются объектом на уровне моего контроллера, и представление обычно не обновляет их напрямую - скорее, представление взаимодействует, когда что-то происходит, отправляя событие или вызывая метод на контроллере, на который он ссылается, или использующий какой-либо аналогичный подход.

У меня такое ощущение, что идиоматический код Какао будет предоставлять свойство delegate в моем настраиваемом представлении, а затем подключать объект контроллера MyDocument (или другой объект уровня контроллера, свисающий с контроллера документа) к представлению, как его делегат, в файле XIB. Затем представление может вызывать некоторые методы, такие как shapeAdded:(NSRect)shape для делегата. Но кажется, что существует множество других способов сделать это, например, заставить контроллер передать ссылку на объект модели (список фигур) непосредственно в пользовательское представление (кажется неправильным) или заставить представление отправить уведомление что контроллер будет слушать (кажется громоздким), а затем контроллер обновляет модель.

Ответы [ 3 ]

5 голосов
/ 25 марта 2009

Наличие делегата - это громкий способ сделать это. Другой способ состоял бы в том, чтобы выставить привязку NSArray в представлении и привязать ее к привязке arrangedObjects контроллера массива, а затем привязать привязку content контроллера массива к тому, кто владеет реальным массивом, содержащим объекты модели. Затем вы можете добавить другие представления на том же контроллере массива, например, список объектов в активном слое.

Это пользовательское представление, вам нужно либо создать IBPlugin для представления привязки в IB, либо связать его программно, отправив представлению сообщение bind: toObject: withKeyPath: options: .

2 голосов
/ 25 марта 2009

В каталоге / Developer / examples / AppKit / Sketch есть очень хороший пример проекта xcode, который является более продвинутой версией того, что вы делаете, но, тем не менее, уместен. В нем есть отличные примеры использования привязок между контроллером и представлением, которые проливают свет на «правильный» способ выполнения действий. В этом примере не используются плагины IB, поэтому вы увидите вызовы связывания вручную и реализованные методы наблюдения.

1 голос
/ 25 марта 2009

Есть несколько сходств между вашим кодом и NSTableView, поэтому я хотел бы взглянуть на использование источника данных (аналогичного вашему делегату) или даже привязок.

...