English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Обобщение и различия между KVC, KVO, Notification и delegate в iOS
1、KVC - это аббревиатура от NSKeyValueCoding, неофициальный протокол, который предоставляет механизм для косвенного доступа к свойствам объекта. Вместо того чтобы вызывать методы Setter и Getter. KVO - это одно из ключевых технологий, реализующихся на основе KVC.
Демо:
@interface myPerson : NSObject { NSString*_name; int _age; int _height; int _weight; } @interface testViewController :UIViewController @property (nonatomic, retain) myPerson*testPerson; @end - (void)testKVC; { testPerson = [[myPerson alloc] init]; NSLog(@"testPerson's init height =%@", [testPerson valueForKey:@"height"]); [testPerson setValue:[NSNumber numberWithInt:168] forKey:@"height"]; NSLog(@"высота testPerson = %@ }
Первый код определяет класс myPerson, у которого есть атрибут _height, но не предоставлены никакие методы getter/setter для доступа. В классе testViewController есть указатель на объект myPerson.
После того как объект myPerson был инстанцирован, по умолчанию доступ к свойству _height этого объекта невозможен, но с помощью KVC мы это сделали, код это функция testKVC.
После выполнения будет напечатано значение:
2015-3-13 11:16:21.970 test[408:c07] начальная высота testPerson = 0
2015-3-13 11:16:21.971 test[408:c07] высота testPerson = 168
Это означает, что действительно было произведено чтение и запись атрибута _height.
Обычные методы KVC:
- (id)valueForKey:(NSString *)key; -(void)setValue:(id)value forKey:(NSString *)key;
Метод valueForKey: читает атрибут объекта по значению ключа, а метод setValue:forKey: записывает атрибут объекта по значению ключа.
Внимание:
(1). Значение ключа должно быть правильным, если оно написано неправильно, будет возникать исключение
(2). Если значение ключа не определено, вызывается метод valueForUndefinedKey:, если вы сами его реализовали, при ошибке значения ключа вызов будет направлен сюда
(3). Из-за повторного вложения ключей класса, существует концепция keyPath, которая использует точку (.) для соединения ключей, что позволяет получить доступ к свойствам по этому пути
(4). NSArray и NSSet поддерживают KVC
2, KVO - это аббревиатура от 'KeyValue Observe', что означает наблюдение за ключами и значениями. Это типичный паттерн наблюдателя, при изменении ключей и значений наблюдатель получает уведомление. В iOS есть механизм уведомлений, который также позволяет получить уведомления, но этот механизм требует наличия центра (Center), в сравнении с KVO он более прост и прямой.
Использование KVO очень просто и состоит из 3 шагов.
1. Зарегистрировать наблюдаемый объект и его свойства addObserver:forKeyPath:options:context:
2. Реализовать метод observeValueForKeyPath:ofObject:change:context:, который автоматически вызывается при изменении наблюдаемого свойства
3. Отменить регистрацию наблюдателя removeObserver:forKeyPath:context:
Демо:
@interface myPerson : NSObject { NSString *_name; int _age; int _height; int _weight; } @end @interface testViewController : UIViewController @property (nonatomic, retain) myPerson *testPerson; - (IBAction)onBtnTest:(id)sender; @end - (void)testKVO { testPerson = [[myPerson alloc] init]; [testPerson addObserver:self forKeyPath:@"height" options:NSKeyValueObservingOptionNew context:nil]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqualToString:@"height"]) { NSLog(@"Высота изменилась! новоеЗначение=%@", [change valueForKey:NSKeyValueChangeNewKey]); } [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } - (IBAction)onBtnTest:(id)sender {}} int h = [[testPerson valueForKey:@"height"] intValue]; [testPerson setValue:[NSNumber numberWithInt:h+1] forKey:@"height"]; NSLog(@"person height=%@", [testPerson valueForKey:@"height"]); } - (void)dealloc { [testPerson removeObserver:self forKeyPath:@"height" context:nil]; [super dealloc]; }
Первый код объявляет класс myPerson, в котором есть свойство _height. В testViewController есть указатель на объект testPerson.
В методе testKVO мы зарегистрировали наблюдение за свойством height объекта testPerson, так что при изменении свойства height объекта testPerson, мы получим уведомление. В этом методе также через параметр NSKeyValueObservingOptionNew запрашивается передача нового значения в dictionary.
Метод observeValueForKeyPath:ofObject:change:context: был перегружен, в этом методе переменная change является NSDictionary объектом, который содержит соответствующие значения.
Следует подчеркнуть, что вызовы обратных вызовов KVO должны быть выполнены, свойства должны быть изменены через методы KVC. Если свойства изменяются через другие методы класса, наблюдатель не получит уведомление.
3. Использование Notification можно увидеть по адресу http://blog.csdn.net/eduora_meimei/article/details/44198909
Различия:
Преимущества delegate :
1.非常に厳格な文法。聞くすべてのイベントは、delegateプロトコルで明確に定義されている必要があります。
2. Если один из методов delegate не реализован, то会出现编译警告/ошибка
3. Протокол должен быть определен в диапазоне действия controller
4. В одном приложении процесс управления является отслеживаемым и идентифицируемым;
5. В одном контроллере можно определить несколько различных протоколов, каждый из которых имеет своих delegates
6. Не требуется участие третьей стороны для поддержания/наблюдения за процессом коммуникации.
7. Возможность получения возвращаемого значения метода протокола. Это означает, что delegate может предоставлять обратную информацию controller
Недостатки :
1. Необходимо определить много кода: 1. Определение протокола; 2. Атрибут delegate controller; 3. Реализация методов delegate в самом delegate;
2. При освобождении объекта代理 необходимо осторожно изменить delegate на nil. В случае неудачи при установке, вызов метода освобождения объекта может привести к памяти crash
3. В одном controller могут быть несколько объектов delegate, которые соблюдают один и тот же протокол, но все же трудно сообщить одному и тому же событию нескольким объектам, хотя это возможно.
Преимущества notification :
1. Не нужно писать много кода, реализация проста;
2. Для одного отправленного уведомления несколько объектов могут отреагировать, то есть реализация 1 к многим способом проста;
3. Controller может передавать объект контекста (dictionary), который содержит информацию о отправке уведомления;
Недостатки :
1. В компиляторном периоде не проверяется, правильно ли обработано уведомление наблюдателями;
2. При освобождении зарегистрированных объектов необходимо取消 регистрацию в центре уведомлений;
3. В процессе отладки трудно отслеживать выполняемые действия и контрольные процессы;
4. Требуется участие третьей стороны для управления связью между object controller и наблюдателями;
5. Controller и наблюдатели должны заранее знать имя уведомления, ключи UserInfodictionary. Если эти ключи не определены в рабочей области, может возникнуть несинхронизация;
6. После отправки уведомления, controller не может получить никакой обратной информации от наблюдателей.
Преимущества KVO :
1. Возможность предоставления простого метода для синхронизации между двумя объектами. Например: синхронизация между model и view;
2. Возможность реагировать на изменения состояния объектов, не созданных нами, то есть на состояние внутренних объектов (SKD объекты), не требуя изменения реализации внутренних объектов;
3. Возможность предоставления текущего и предыдущего значений наблюдаемых свойств;
4. Наблюдение за свойствами с помощью key paths, поэтому также можно наблюдать за вложенными объектами;
5. Завершено абстрагирование наблюдаемого объекта, так как не требуется дополнительного кода для того, чтобы позволить наблюдаемым значениям быть наблюдаемыми
Недостатки :
1.Мы должны определить наблюдаемые свойства с помощью strings. Таким образом, в компиляторе не会出现 предупреждений и проверок;
2. Реконструкция свойств приведет к тому, что наш наблюдательный код больше не будет доступен;
3. Комплексные «IF» условия требуют, чтобы объект наблюдал за несколькими значениями. Это потому, что все наблюдательные коды указывают на один метод;
4. При освобождении наблюдателя не нужно удалять наблюдателя.
1. Эффективность肯定是 delegate выше, чем NSNotification.
Методы delegate более прямые, их наиболее типичной особенностью является то, что методы delegate часто требуют внимания к возвращаемому значению, то есть результату метода delegate. Например, -windowShouldClose:, необходимо учитывать, возвращает ли он yes или no. Поэтому методы delegate часто содержат слово should, то есть, если вы становитесь моим delegate, я спрашиваю вас, хотите ли вы закрыть окно? Вам нужно дать мне ответ, и я буду принимать решение о следующем шаге на основе вашего ответа. Напротив, у notification最大的特色 является безразличие к позиции получателя, я просто发布 уведомление, и вам решать, принимать ли его или нет, и я не关心 результат. Поэтому notification часто используется с словом did, например, NSWindowDidResizeNotification, после того как NSWindow объект выпускает это уведомление, он больше не заботится о нем и не ждет реакции получателя.
2. Различия между KVO и NSNotification:
Как и delegate, KVO и NSNotification играют роль коммуникации между классами, в отличие от delegate, 1) обе из них отвечают за отправку уведомлений, и больше не заботятся о других вещах, поэтому они не возвращают значения; 2) delegate является一对一, а эти могут быть одним к многим. У них также есть свои особенности.
Спасибо за чтение, надеюсь, это поможет вам, спасибо за поддержку нашего сайта!