Как может drawRect запросить / rcv изображение, недавно вычисленное моделью? - PullRequest
0 голосов
/ 24 января 2011

У меня первое приложение, работающее на iphone / ipad, которое использует Core Graphics и распознаватели жестов (НЕ OpenGL или сенсорные события).Приложение, представление и контроллер были настроены с использованием IB.Это просто View внутри ViewController.Я добавил CG-вызовы для включения в CG-контекст.Жесты добавляются в представление, но обрабатываются в контроллере представления.Контроллер представления использует средства доступа для изменения переменных, которые определяют, что отображается в представлении.Вычисление (то есть модель) встроено в представление.Приложение работает довольно хорошо, но я хотел бы добавить такие функции, как отправка по электронной почте и сохранение того, что было нарисовано.(Я знаю, что мне понадобятся другие графические контексты).

Обычная мудрость подсказывает мне, что мне нужно использовать парадигму MVC, что означает выделение модели из вида в ее собственный объект.Итак, я пересмотрел код.Я вручную добавил объект NSObject для модели, который приятно содержит данные и необходимые методы.Нет ошибок компиляции или предупреждений.

Теперь, когда DrawRect представления запущен, я хочу получить обновленное изображение из модели через контроллер.В ключевом месте, где я ожидаю возвращения изображения, возвращается NULL.Возможно, у меня нет правильной ссылки на объект (ы), но я слишком смущен, чтобы урезать туман, и я работаю в вакууме, поэтому я заручаюсь вашей помощью.Спасибо за чтение.

РЕЗЮМЕ и ВОПРОС

Контроллер представления всегда имеет текущие параметры, которые он может передать модели.Модель может вычислить растровое изображение с учетом этих параметров.Я почти уверен, что у меня так много проблем.

Мой вопрос (сформулирован по-разному):

Каков наилучший способ получить изображение с модели на вид (черезконтроллер: ^) Как View должен посылать сообщение контроллеру представления, чтобы инициировать запрос?

Как модель может вернуть изображение в контроллер?Я предполагаю, что просто передам CGContextRef через любую цепочку, которую вы рекомендуете.

Обо мне: я новичок в OOP, Objective-C, Xcode и IB.Я несколько раз смотрел большинство лекций Стэнфорда, изучал книги Гольдштейновских чайников, просматривал документы Apple.Новичку трудно подобрать ответы соответствующего уровня из этих источников.Мне просто нужно больше "опыта".Я такой зеленый, я даже не уверен, как ссылаться на контроллер представления, кроме как включить «myViewController * viewController» в определение интерфейса представления!Я гуглил и читал ответы на подобные вопросы здесь, на Stackoverflow.Я не могу поверить, я не нашел ничего подходящего.Я надеюсь, что один или два практических принципа послужат моим руководством.

Пожалуйста, сообщите.

Это похоже на ссылку на модель-данные-в-виде-экземпляр-отрисовку, который не получил удовлетворительного ответа.

Ответы [ 4 ]

0 голосов
/ 25 января 2011

Во-первых, вам, вероятно, потребуется перерисовать всякий раз, когда ваши параметры могут привести к изменению данных.Таким образом, вместо запроса новых данных, когда представление необходимо перерисовать, попросите контроллер представления или представления контролировать данные, чтобы при изменении представления представление перерисовывалось.drawRect ДЕЙСТВИТЕЛЬНО не должен запрашивать данные, особенно не косвенно из контроллера представления, это нарушает всю конструкцию MVC, потому что представление должно знать о своем контроллере представления (чтобы он мог запрашивать данные).Во-вторых, для скорости используйте cgcontext, чтобы нарисовать изображение напрямую: CGContextDrawImage(GContextRef c, CGRect rect, CGImageRef image);.

0 голосов
/ 24 января 2011

Если я вас правильно понимаю, вид должен получить новое изображение, когда изображение в модели изменяется.Как сказал Уилл, вы можете использовать уведомления или наблюдение значения ключа.Поскольку ваша модель не должна знать о представлении, а представление не должно иметь четкой ссылки на модель.Для этого добавьте это в метод viewDidLoad в вашем контроллере представления:

[model addObserver:self.view forKeyPath:@"<replace this with the name of the image property in the model>" options:NSKeyValueChangeNewKey context:NULL];

, затем в вашем подклассе uiview создайте этот метод:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if ([keyPath isEqual:@"<replace this with the name of the image property in the model>"] {
         // set an image property that has been added to the uiview
         // the image property should be a weak reference ie. (nonatomic, assign)
         self.image = [change valueForKey:NSKeyValueChangeNewKey];
         [self setNeedsDisplay];
    }
}

и, наконец, в вашем методе drawRect:нарисуйте изображение.

0 голосов
/ 25 января 2011

КАК Я НАСТРОИЛ СВЯЗЬ МЕЖДУ ПРОСМОТРОМ | КОНТРОЛЛЕР | МОДЕЛЬ:

view | controller - из метода loadView контроллера представления я отправил в представление сообщение «hello:», содержащее ссылку на «self». В методе hello (объекта view) я спрятал этот указатель на viewcontroller в глобальной переменной для дальнейшего использования.

controller | model - у меня был контроллер вида, выделяющий / инициализирующий экземпляр объекта модели и сохраняющий указатель на него в глобальной переменной в контроллере вида.

Мне удалось использовать эти два указателя в качестве моста от вида к модели, пройдя вверх и снова через контроллер vew. Я не знаю, что я делаю достаточно хорошо, чтобы знать, мог ли я выполнить эту связь с IB или нет.

ЗАПИСЬ КАК ЭТО РАБОТАЕТ

drawRect отправляет запрос / сообщение для обновленного изображения в viewcontroller.

Контроллер представления может действовать так, как ему хочется, но, поскольку он имеет параметры, настроенные обработчиками жестов, он может передать конкретный запрос модели с этими параметрами.

Затем модель начинает работать с CG, использует CGBitmapContextCreateImage (из растрового контекста в модели) и возвращает CGImageRef (в контроллер представления). Затем контроллер представления просто возвращает тот же CGImageRef, что и результат исходного запроса. Затем drawRect делает [[UIImage imageWithCGImage: modelImage] drawInRect: rect], чтобы поместить изображение в представление.

ВОЗМОЖНЫЕ ВНИЗ, ЗАКЛЮЧИТЕЛЬНЫЕ МЫСЛИ

Это / может / медленнее, но это может быть просто паранойя. Модель обычно рисует 8K линий или больше, чтобы сделать растровое изображение, но представление не должно делать так много работы, чтобы скопировать получившиеся пиксели. Я должен использовать инструменты, чтобы увидеть, что случилось.

Также меня беспокоит качество изображения. Кажется хорошо. Я не думаю, что что-то теряю, сначала рисуя в контексте CGbitmap, затем проходя через CGBitmapContextCreateImage, а затем, наконец, UIImage imageWithCGImage, как указано выше. Все тот же точный размер.

0 голосов
/ 24 января 2011

Одна вещь, которую вы можете попробовать, если она вам подходит, - это использовать NSNotifications.

Представление получает информацию о жестах и ​​отправляет высокоуровневые события в контроллер (посредством прямого обмена сообщениями). Контроллер принимает эти события высокого уровня и вносит изменения в модель. Модель использует эти изменения и затем отправляет NSNotifications всем, кто обеспокоен этими изменениями.

Представление уже знает о модели, поскольку именно так она отображает свои данные, поэтому представление сможет легко подписаться на эти изменения. Модель на самом деле не знает о представлении, поэтому должна отправлять сообщения непосредственно в него. Однако что-то где-то заинтересовано в изменениях модели, поэтому она использует NSNotifications для трансляции и публикации этой информации. Таким образом, особенно со сложной моделью и / или более простым View, View подписываются только на то, что им интересно. Вы также можете легко иметь более одного View (или любого другого), прослушивающего NSNotifications одновременно.

Еще одна опция - Кодирование значения ключа / Наблюдение, которое поддерживает iPhone, но оно не так укоренилось, как в Какао на Mac. Это обрабатывает большую часть уведомлений для вас полуавтоматически, так что вы можете рассмотреть это также.

...