Это вопрос Cocoa n00b - я много лет программировал приложения с графическим интерфейсом в других средах, но теперь я хотел бы понять, что такое «идиоматический 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
добавляются к shapes
каждый раз, когда пользователь выполняет последовательность нажатия/перетаскивания/поднятия мыши, которую я также реализовал в этом пользовательском представлении. Вот мой вопрос:
Если бы это было "настоящее" приложение Cocoa, каким идиоматическим способом мое пользовательское представление могло бы обновить свою модель?
Другими словами, как пользовательское представление должно уведомить контроллер о том, что в список фигур необходимо добавить еще одну фигуру? Прямо сейчас представление отслеживает фигуры в своем собственном NSMutableArray
, что прекрасно в качестве детали реализации, но я не хочу выставлять этот массив как часть общедоступного API моего пользовательского представления. Кроме того, я хотел бы поместить проверку ошибок, сохранение/загрузку и отмену кода в централизованное место, такое как контроллер, вместо того, чтобы засорять все мои пользовательские представления. По моему прошлому опыту работы с другими средами программирования с графическим интерфейсом, модели управляются объектом на моем уровне контроллера, и представление обычно не обновляет их напрямую — скорее, представление сообщает, когда что-то происходит, отправляя событие или вызывая метод на контроллере, на который он ссылается, или используя какой-либо подход с аналогичной развязкой.
Я нутром чувствую, что идиоматический код Cocoa выставит свойство delegate
в моем пользовательском представлении, а затем подключит объект контроллера MyDocument
(или другой объект уровня контроллера, свисающий с контроллера документа) к представлению в качестве его делегата в xib. файл. Затем представление может вызывать некоторые методы, такие как shapeAdded:(NSRect)shape
для делегата. Но похоже, что есть множество других способов сделать это, например, передать контроллеру ссылку на объект модели (список фигур) непосредственно в пользовательское представление (кажется неправильным) или заставить представление отправлять уведомление который будет слушать контроллер (кажется громоздким), а затем контроллер обновляет модель.