2013-09-23 2 views
1

У меня есть простое приложение для работы с i/o для файла plist в нескольких потоках из 2 представлений. Так что теперь у меня есть поле с UUID в PLIST и когда я удалить элемент - DataManager генерирует сообщение через NSNotificationCenter с UUID на удаленный объект,Альтернативный способ уведомить мнение об изменении модели?

[[NSNotificationCenter defaultCenter] postNotificationName:EADataManagerItemDeleted 
                  object:nil 
                  userInfo:userInfo]; 

поэтому вид прослушивает сообщение и если принимаемой UUID это то же самое, что и отображение вида - система может реагировать на это.

[[NSNotificationCenter defaultCenter] addObserver:self 
             selector:@selector(receiveNotification:) 
              name:EADataManagerItemDeleted 
              object:nil]; 

Но у меня есть информация, которую мы используем NSNotificationCenter в очень тяжелых случаях, когда мы не имеем ни малейшего представления о том, как получить объект по-другому. Поэтому, пожалуйста, как я могу понять, что элемент на экране был изменен в другом потоке? Благодарю. Мой TechLead сказал мне использовать класс NSException для этих целей, но не может видеть решение в любом случае.

ответ

1

Прошу, пожалуйста, не пытаться использовать NSExceptions для признания недействительным. Я даже не знаю, как это работает, но, пожалуйста, не пытайтесь. В отличие от других фреймворков/языков (например, Java или .NET), в Cocoa исключения обычно означают, что «что-то пошло не так, и приложение должно завершиться». (Да, существует несколько исключений из этого правила, но «просмотр недействительности» не является одним из них.)

Первое, что нужно знать, это то, что объекты пользовательского интерфейса (т.е. виды) обычно рассматриваются как основная тема только. Поэтому, если вы мутируете свою модель в фоновом потоке, недействительность представления должна быть привязана к основному потоку. У GCD есть возможности для обработки этого (dispatch_get_main_queue), но есть и другие, такие как -[NSObject performSelectorOnMainThread:...] и CFRunLoopPerformBlock.

Следующее, что нужно знать, это то, что если вы собираетесь это сделать (например, прочитайте свою модель в основном потоке, чтобы заполнить пользовательский интерфейс и обновить модель из фоновых потоков), вам нужно будет иметь какую-то блокировку чтобы никакие фоновые потоки не мутировали модель, пока основной поток пытается ее прочитать. Вы можете заблокировать недействительность основного потока без блокировки, но когда взгляды перейдут на повторную проверку (т. Е. Макет и рисование), вы захотите сделать соответствующую блокировку для объектов модели, представляемых для предотвращения повреждения данных. Управление этими замками может быстро стать нетривиальным. (Хотя частные параллельные очереди НОД доступ с dispatch_(a)sync & dispatch_barrier_(a)sync являются очень хорошим местом для начала.)

Один общий шаблон, который позволяет избежать большинства сложности запирающего должен иметь фоновые потоки выполняют свою работу на копию модели а затем отправить не только недействительность представления, но и операцию мутации модели обратно в основной поток, поэтому с точки зрения «одной, истинной модели» она всегда является основным потоком, и в этом случае вам не нужно беспокоиться о блокировке. Если вы можете так поступать, это спасет вас от горя.

На OSX (но не на iOS) есть привязки Cocoa, в которых используется наблюдение за ключевыми значениями (с рядом непрозрачной «магии» между ними), чтобы автоматически аннулировать и обновлять связанный интерфейс при изменении модели. Связывание какао не существует на iOS, но стоит упомянуть, что KVO делает, и отправленные ему уведомления могут использоваться для аннулирования вида. Важно знать, что уведомления KVO отправляются синхронно в потоке, в котором происходит мутация, поэтому вы захотите маршализовать свои мутации обратно в основной поток.

И, наконец, использование NSNotificationCenter не освобождает вас от беспокойства по поводу блокировки и перекрестных уведомлений ни потому, что, как KVO, NSNotifications доставляются синхронно в потоке, на котором они размещаются.Отправка NSNotification в фоновом потоке, для которого есть наблюдатели UIViews, также вызовет проблемы.

+0

спасибо за так много слов, да я меняю модель в фоновом потоке и, конечно же, отправляю NSNotification в основной поток, и я использую GCD, да, но я не вижу другой реализации, кроме NSNotificationCenter. Из курса Стэнфордского университета я узнал, что модель может уведомлять о своем состоянии с помощью KVO и уведомлений. Поэтому для работы с потоками у меня нет проблем, но NSNotificationCenter - очень сложный инструмент для понимания отношений между классами, поэтому мне нужно решить другим способом. – ShurupuS

+0

'NSNotificationCenter' и KVO - это два механизма, предоставляемые структурами для обработки этого - Я не знаю никаких других абстрактных средств уведомления в iOS. Если ни один из них не будет работать на вас, вам, вероятно, придется написать что-то другое с нуля (и это почти наверняка не должно включать в себя «NSException'). Что касается механизмов уведомления, NSNotificationCenter довольно прост, поэтому, я думаю, я не понимаю проблему. – ipmcc

+0

Я тоже не могу это понять, но, насколько я понимаю, это слабая точка моей тестовой задачи для моей будущей работы, спасибо, я попробую gooooogle узнать больше о MVC. – ShurupuS

2

Использование KVO (наблюдение за ключом).

Там хорошая и углубленная статья на NSHipster: http://nshipster.com/key-value-observing/

с какао (на рабочем столе), вы можете использовать привязки с Interface Builder, на Cocoa Touch (IOS), вы должны использовать его программно, но это относительно легко, как только вы знаете, как:

Вкратце вы можете выбрать для отслеживания любых свойств известных объектов. В вашем случае весь этот код переходит в ваш ViewController. Я предполагаю (и рекомендую), чтобы ваш viewController ссылался на ваш объект модели (dataManager). Хотя ваша модель не должна иметь никаких ссылок на ваш viewController; вот где вы будете использовать Key-Value-Observing. Другими словами: ваш контроллер будет наблюдать изменения значений в свойствах вашей модели (-> a.k.a "keys").

Во-первых, зарегистрироваться для KVO:

[dataManager addObserver:self 
       forKeyPath:@"nameOfThingIAmInterestedIn" 
       options:NSKeyValueObservingOptionNew 
       context:NULL]; 

не забудьте удалить наблюдения (например, в dealloc)

[dataManager removeObserver:self forKeyPath:@"nameOfThingIAmInterestedIn"]; 

и, наконец, реализовать этот метод для получения уведомлений KVO. В вашем случае вы должны dispatch_async на главную очереди, как вы хотите, чтобы обновить представление (в основном потоке):

-(void)observeValueForKeyPath:(NSString *)keyPath 
        ofObject:(id)object 
         change:(NSDictionary *)change 
         context:(void *)context 
{ 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     NSLog(@"KVO: %@ changed property %@ to value %@", object, keyPath, change); 
    } 
} 

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

Смежные вопросы