Краткий ответ:
Когда состояние вашего представления изменяется так, что оно будет отображаться по-другому, вам нужно вызвать - [NSView setNeedsDisplay:]. Это приведет к вызову drawRect: метод вашего представления в ближайшем будущем. Вы никогда не должны вызывать drawRect: себя. Это обратный вызов, который вызывается от вашего имени.
Когда в вашем приложении происходят события, которые заставляют вас захотеть изменить свой чертеж, записать состояние о том, что произошло, в переменные экземпляра, вызвать setNeedsDisplay: и затем позже при вызове drawRect: создайте новый чертеж.
Длинный ответ:
В Какао рисование окон выполняется с помощью модели извлечения / аннулирования. Это означает, что у окна есть представление о том, нужно ли ему рисовать, и когда оно думает, что ему нужно рисовать, оно рисует один раз за цикл событий.
Если вы не знакомы с циклами событий, вы можете прочитать о них в Wikipedia
На верхнем уровне приложения вы можете представить, что Cocoa делает это:
while (1) {
NSArray *events = [self waitForEvents];
[self doEvents:events];
}
Где события - это, например, движение мыши, нажатие клавиатуры и отключение таймеров.
NSView имеет метод - [NSView setNeedsDisplay:]. Он принимает логический параметр. Когда этот метод вызывается, окно лишает законной силы область рисования для этого вида и планирует событие на будущее, чтобы выполнить перерисовку - но только если не запланировано ранее существующее событие перерисовки.
Когда runloop вращается в следующий раз, представления, помеченные с помощью setNeedsDisplay: перерисовываются. Это означает, что вы можете вызывать setNeedsDisplay: несколько раз подряд и рисование будет объединено в один вызов drawRect: в будущем. Это важно с точки зрения производительности и означает, что вы можете делать такие вещи, как изменение фрейма вида несколько раз в одном методе, но он будет нарисован только один раз в конечном местоположении.