SlideShare a Scribd company logo
iOS Internship 2014
Key-Value mechanism
Key-Value Coding
Key-Value Observing
лекция 9
Key-Value mechanism
Key-Value mechanism
KVC — механизм, позволяющий обращаться к свойствам объекта, используя строковые
идентификаторы — ключи (Key). Ключи можно выстраивать в цепочку (KeyPath), обращаясь к
вложенным свойствам. KVC основывается на методах протокола NSKeyValueCoding .
Это позволяет решить во время выполнения к какому свойству обратиться.
NSString *valueB = [myObject valueForKey:@"someString"];
NSString *valueC = [myObject valueForKeyPath:@"parentObject.someString"];
Key-Value Coding
Key-Value mechanism
@interface Person : NSObject
@property (strong, nonatomic) NSString *name;
@property (strong, nonatomic) NSNumber *age;
//...
@end
{
[
"name": "Alice",
"age": 22,
...
],
[
"name": "Bob",
"age": 24,
...
]
}
Нужно создать массив объектов Person из полученного JSON
Key-Value Coding
Key-Value mechanism
Key-Value Coding
NSArray *personsDescriptions = /*...*/;
NSMutableArray *persons = /*...*/;
// Вручную работаем с каждым свойством
for (NSDictionary *personDescription in personsDescriptions) {
Person *person = [[Person alloc] init];
person.name = personDescription[@"name"];
person.age = personDescription[@"age"];
//...
}
Key-Value mechanism
Key-Value Coding
NSArray *personsDescriptions = /*...*/;
NSMutableArray *persons = /*...*/;
// Вручную работаем с каждым свойством
for (NSDictionary *personDescription in personsDescriptions) {
Person *person = [[Person alloc] init];
person.name = personDescription[@"name"];
person.age = personDescription[@"age"];
//...
}
// Автоматический проход по всем свойствам
for (NSDictionary *personDescription in personsDescriptions) {
Person *person = [[Person alloc] init];
for (NSString *key in personDescription.allKeys) {
[person setValue:personDescription[key] forKey:key];
}
}
Key-Value mechanism
Key-Value Coding
NSArray *personsDescriptions = /*...*/;
NSMutableArray *persons = /*...*/;
// Вручную работаем с каждым свойством
for (NSDictionary *personDescription in personsDescriptions) {
Person *person = [[Person alloc] init];
person.name = personDescription[@"name"];
person.age = personDescription[@"age"];
//...
}
// Автоматический проход по всем свойствам
for (NSDictionary *personDescription in personsDescriptions) {
Person *person = [[Person alloc] init];
for (NSString *key in personDescription.allKeys) {
[person setValue:personDescription[key] forKey:key];
}
}
Нужна осторожность: только мы отвечаем за правильность ключей.
Key-Value mechanism
KVC позволяет включать в качестве ключей в KeyPath не только объекты, но и коллекции
объектов. На выходе мы получим коллекцию, аггрегирующую значения заданного поля у всех
элементов коллекции.
@interface Person : NSObject
@property (strong, nonatomic) NSString *name;
@property (strong, nonatomic) NSNumber *age;
//...
@end
//...
@property (strong, nonatomic) NSArray *myPersons;
//...
NSArray *allNames = [self valueForKeyPath:@"myPersons.name"];
Key-Value Coding
Key-Value mechanism
KVC предоставляет несколько операторов для обработки значений элементов коллекции:
@avg, @max, @min, @distinctUnionOfObjects и др.
@interface Person : NSObject
@property (strong, nonatomic) NSString *name;
@property (strong, nonatomic) NSNumber *age;
//...
@end
//...
@property (strong, nonatomic) NSArray *myPersons;
//...
NSArray *avgAge = [self valueForKeyPath:@"myPersons.@avg.age"];
Key-Value Coding
Key-Value mechanism
NSPredicate позволяет делать достаточно хитрые запросы (с фильтрами и выражениями), в том числе при
доступе к значениям через KVC. Синтаксис выражений похож на SQL запросы и может использовать
регулярные выражения.
@interface Person : NSObject
@property (strong, nonatomic) NSString *name;
@property (strong, nonatomic) NSNumber *age;
//...
@end
//...
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name CONTAINS 'Bob'"];
NSLog(@"Bobs: %@", [people filteredArrayUsingPredicate:predicate]);
NSPredicate
Key-Value mechanism
По умолчанию обращение по несуществующему ключу вызывает исключение, поэтому нужно
реализовать одну из политик:
● Следить за тем, что мы не обращаемся к несуществующим ключам
● Переопределить методы, обрабатывающие обращение к несуществующим ключам
(valueForUndefinedKey: и setValue: forUndefinedKey: )
Значения при использовании KVC имеют тип id, поэтому:
● При обращении к скаляру (BOOL, int, float, ...) через KVC, он автоматически
оборачивается в NSNumber.
● При обращении к структуре (struct) через KVC, она автоматически оборачивается в
NSValue.
● При присваивании значения nil скаляру через KVC, вызывается метод
setNilValueForKey: , в котором нужно определить желаемое поведение.
Key-Value Coding
Key-Value mechanism
Для поддержки работы KVC нужно правильно именовать методы-акцессоры:
● Имя геттера должно совпадать с именем свойства
● Имя сеттера должно иметь префикс set
@property (strong, nonatomic) NSString *name;
//...
- (NSString *)name {...}
- (void)setName:(NSString *)name {...}
Key-Value Coding
Key-Value mechanism
Key-Value Coding
Чтобы обеспечить поддержку KVC/KVO для свойства, нужно соблюдать правила руководства
по KVC compliance.
По умолчанию свойства стандартных классов нельзя считать KVC-совместимыми, а
документация явно указывает какие свойства обладают этим свойством.
Key-Value mechanism
KVO — механизм поверх KVC, реализующий автоматическую нотификацию объекта об
изменениях значений свойств (в общем случае) другого объекта. (паттерн Observer)
Объект, который хочет получать такие нотификации должен:
● Подписаться на нотификации, указав получателя, объект и KeyPath для отслеживания,
свой контекст, дополнительные опции (например нотификация до или после изменения
значения).
● Обрабатывать полученные нотификации, проверив что они действительно должны быть
обработаны. (Родительский класс мог так же подписаться на нотификации и их нужно
передать в super).
● По необходимости или в конце жизненного цикла отписаться от всех ранее созданных
подписок.
Key-Value Observing
Key-Value mechanism
KVO — мощный механизм, который не терпит ошибок…
Key-Value Observing
Key-Value mechanism
● Создаём контекст. Он помогает определить, принадлежат ли нам полученные
нотификации.
static void *const myContext = (void *)&myContext;
● Подписываемся на изменения значений. (например в init)
[self.myPerson addObserver:self
forKeyPath:@"name"
options:NSKeyValueObservingOptionNew
context:myContext];
● Отписываемся от нотификаций. (например в dealloc)
[self.myPerson removeObserver:self
forKeyPath:@"name"
context:myContext];
Key-Value Observing
Key-Value mechanism
● Получаем и обрабатываем нотификации.
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
if (context == myContext) {
Person *person = (Person *)object;
NSLog(@"New value is %@.", person.name);
}
else {
[super observeValueForKeyPath:keyPath
ofObject:object
change:change
context:context];
}
}
Key-Value Observing
Key-Value mechanism
KVO поддерживает свойства, не имеющие под собой ivar, например для которых значение
вычисляется каждый раз в геттере.
@property (copy, nonatomic) NSString *firstName;
@property (copy, nonatomic) NSString *lastName;
@property (readonly, nonatomic) NSString *fullName;
- (NSString *)fullName
{
return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];
}
Key-Value Observing
Key-Value mechanism
KVO поддерживает свойства, не имеющие под собой ivar, например для которых значение
вычисляется каждый раз в геттере.
+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key
{
NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key];
if ([key isEqualToString:@"fullName"]) {
NSArray *affectingKeys = @[@"lastName", @"firstName"];
keyPaths = [keyPaths setByAddingObjectsFromArray:affectingKeys];
}
return keyPaths;
}
Key-Value Observing
Key-Value mechanism
● Нотификации от всех объектов и всех KeyPath приходят в один обработчик.
● Если мы переименовали свойство, мы ответственны за обновление всех строк с KeyPath, куда это
свойство входило.
● Каждый объект должен обрабатывать все те и только те нотификации, на которые он подписан. (Нельзя
отдавать в super свою нотификацию, не стоит обрабатывать нотификации, предназначенные для
super.)
● Нельзя не отписываться от нотификаций, на которые мы подписались.
● Нельзя отписываться дважды от одной и той же нотификации.
● Нельзя проверить подписан ли объект на ту или иную нотификацию.
● Если кто-то использует свойство для KVO, к нему нельзя обращаться через ivar, или нужно вручную
нотифицировать об изменении значения (willChangeValueForKey: / didChangeValueForKey:).
● KVO с трудом поддерживает отслеживание изменений внутри коллекции.
Key-Value Observing
Key-Value mechanism
Для избавления от страданий создано много вариантов обёрток, скрывающих API KVO.
● ReactiveCocoa
[RACObserve(model, keyname) subscribeNext:^(NSString *newValue) {
//...
}];
● KVOBlocks
[model
addObserver:self
forKeyPath::@"keyname"
options:NSKeyValueObservingOptionNew
context:nil
withBlock:^(NSDictionary *change, void *context) {
//...
}];
Key-Value Observing

More Related Content

What's hot

Java tricks for high-load server programming
Java tricks for high-load server programmingJava tricks for high-load server programming
Java tricks for high-load server programmingAndrei Pangin
 
Memory managment in i os (1)
Memory managment in i os (1)Memory managment in i os (1)
Memory managment in i os (1)it-park
 
Thread
ThreadThread
Введение в Realm.io
Введение в Realm.ioВведение в Realm.io
Введение в Realm.io
Nikolay Yasinskiy
 
Владимир Горбенко «Использование блоков в Objective-C»
Владимир Горбенко «Использование блоков в Objective-C»Владимир Горбенко «Использование блоков в Objective-C»
Владимир Горбенко «Использование блоков в Objective-C»e-Legion
 
Курсы актерского мастерства
Курсы актерского мастерстваКурсы актерского мастерства
Курсы актерского мастерства
Vasil Remeniuk
 
Артемий Гарин "Выбор лучшего хранилища в Android (cпойлер: Realm)"
Артемий Гарин "Выбор лучшего хранилища в Android (cпойлер: Realm)"Артемий Гарин "Выбор лучшего хранилища в Android (cпойлер: Realm)"
Артемий Гарин "Выбор лучшего хранилища в Android (cпойлер: Realm)"
IT Event
 
Выжимаем из сервера максимум (Андрей Паньгин)
Выжимаем из сервера максимум (Андрей Паньгин)Выжимаем из сервера максимум (Андрей Паньгин)
Выжимаем из сервера максимум (Андрей Паньгин)Ontico
 
Underscore js
Underscore jsUnderscore js
Underscore js
Olya Nosova
 
Yii development
Yii developmentYii development
Yii developmentMageCloud
 
JavaScript-библиотека
JavaScript-библиотекаJavaScript-библиотека
JavaScript-библиотека
Vasya Petrov
 
Хватит писать инфраструктурный код
Хватит писать инфраструктурный кодХватит писать инфраструктурный код
Хватит писать инфраструктурный код
Vadim Martynov
 
Эффективное программирование на NodeJS
Эффективное программирование на NodeJSЭффективное программирование на NodeJS
Эффективное программирование на NodeJS
Yura Bogdanov
 
03 коллекции
03   коллекции03   коллекции
03 коллекции
Noveo
 
Developing highload servers with Java
Developing highload servers with JavaDeveloping highload servers with Java
Developing highload servers with Java
Andrei Pangin
 
Незаурядная Java как инструмент разработки высоконагруженного сервера
Незаурядная Java как инструмент разработки высоконагруженного сервераНезаурядная Java как инструмент разработки высоконагруженного сервера
Незаурядная Java как инструмент разработки высоконагруженного сервера
odnoklassniki.ru
 
NFX
NFXNFX
Хранение данных в iPhone. (FMDB, SQL-Persistence, CoreData)
Хранение данных в iPhone. (FMDB, SQL-Persistence, CoreData)Хранение данных в iPhone. (FMDB, SQL-Persistence, CoreData)
Хранение данных в iPhone. (FMDB, SQL-Persistence, CoreData)Yandex
 
RDSDataSource: Promises
RDSDataSource: PromisesRDSDataSource: Promises
RDSDataSource: Promises
RAMBLER&Co
 

What's hot (20)

Java tricks for high-load server programming
Java tricks for high-load server programmingJava tricks for high-load server programming
Java tricks for high-load server programming
 
Memory managment in i os (1)
Memory managment in i os (1)Memory managment in i os (1)
Memory managment in i os (1)
 
Thread
ThreadThread
Thread
 
Введение в Realm.io
Введение в Realm.ioВведение в Realm.io
Введение в Realm.io
 
Владимир Горбенко «Использование блоков в Objective-C»
Владимир Горбенко «Использование блоков в Objective-C»Владимир Горбенко «Использование блоков в Objective-C»
Владимир Горбенко «Использование блоков в Objective-C»
 
Курсы актерского мастерства
Курсы актерского мастерстваКурсы актерского мастерства
Курсы актерского мастерства
 
Артемий Гарин "Выбор лучшего хранилища в Android (cпойлер: Realm)"
Артемий Гарин "Выбор лучшего хранилища в Android (cпойлер: Realm)"Артемий Гарин "Выбор лучшего хранилища в Android (cпойлер: Realm)"
Артемий Гарин "Выбор лучшего хранилища в Android (cпойлер: Realm)"
 
Выжимаем из сервера максимум (Андрей Паньгин)
Выжимаем из сервера максимум (Андрей Паньгин)Выжимаем из сервера максимум (Андрей Паньгин)
Выжимаем из сервера максимум (Андрей Паньгин)
 
Underscore js
Underscore jsUnderscore js
Underscore js
 
Yii development
Yii developmentYii development
Yii development
 
JavaScript-библиотека
JavaScript-библиотекаJavaScript-библиотека
JavaScript-библиотека
 
Хватит писать инфраструктурный код
Хватит писать инфраструктурный кодХватит писать инфраструктурный код
Хватит писать инфраструктурный код
 
Эффективное программирование на NodeJS
Эффективное программирование на NodeJSЭффективное программирование на NodeJS
Эффективное программирование на NodeJS
 
03 коллекции
03   коллекции03   коллекции
03 коллекции
 
Асинхронный JavaScript
Асинхронный JavaScriptАсинхронный JavaScript
Асинхронный JavaScript
 
Developing highload servers with Java
Developing highload servers with JavaDeveloping highload servers with Java
Developing highload servers with Java
 
Незаурядная Java как инструмент разработки высоконагруженного сервера
Незаурядная Java как инструмент разработки высоконагруженного сервераНезаурядная Java как инструмент разработки высоконагруженного сервера
Незаурядная Java как инструмент разработки высоконагруженного сервера
 
NFX
NFXNFX
NFX
 
Хранение данных в iPhone. (FMDB, SQL-Persistence, CoreData)
Хранение данных в iPhone. (FMDB, SQL-Persistence, CoreData)Хранение данных в iPhone. (FMDB, SQL-Persistence, CoreData)
Хранение данных в iPhone. (FMDB, SQL-Persistence, CoreData)
 
RDSDataSource: Promises
RDSDataSource: PromisesRDSDataSource: Promises
RDSDataSource: Promises
 

Similar to Kvc, kvo

Школа-студия разработки приложений для iOS. Лекция 1. Objective-C
Школа-студия разработки приложений для iOS. Лекция 1. Objective-CШкола-студия разработки приложений для iOS. Лекция 1. Objective-C
Школа-студия разработки приложений для iOS. Лекция 1. Objective-CГлеб Тарасов
 
Active Record for CoreData
Active Record for CoreDataActive Record for CoreData
Active Record for CoreData
Dmitriy Kuragin
 
Школа-студия разработки для iOS. Лекция 4. Работа с данными
Школа-студия разработки для iOS. Лекция 4. Работа с даннымиШкола-студия разработки для iOS. Лекция 4. Работа с данными
Школа-студия разработки для iOS. Лекция 4. Работа с даннымиГлеб Тарасов
 
7 кашкута
7 кашкута7 кашкута
7 кашкутаCodeFest
 
Перспективы функционального подхода
Перспективы функционального подходаПерспективы функционального подхода
Перспективы функционального подхода
Igor Kashkuta
 
Курсы по мобильной разработке. 1 лекция. Знакомство с iOS
Курсы по мобильной разработке. 1 лекция. Знакомство с iOSКурсы по мобильной разработке. 1 лекция. Знакомство с iOS
Курсы по мобильной разработке. 1 лекция. Знакомство с iOSГлеб Тарасов
 
Ecma script 6 in action
Ecma script 6 in actionEcma script 6 in action
Ecma script 6 in action
Yuri Trukhin
 
Solit 2014, EcmaScript 6 in Action, Трухин Юрий
Solit 2014, EcmaScript 6 in Action, Трухин Юрий Solit 2014, EcmaScript 6 in Action, Трухин Юрий
Solit 2014, EcmaScript 6 in Action, Трухин Юрий
solit
 
Интуит. Разработка приложений для iOS. Лекция 8. Работа с данными
Интуит. Разработка приложений для iOS. Лекция 8. Работа с даннымиИнтуит. Разработка приложений для iOS. Лекция 8. Работа с данными
Интуит. Разработка приложений для iOS. Лекция 8. Работа с даннымиГлеб Тарасов
 
Объектно-ориентированное программирование. Лекции 9 и 10
Объектно-ориентированное программирование. Лекции 9 и 10Объектно-ориентированное программирование. Лекции 9 и 10
Объектно-ориентированное программирование. Лекции 9 и 10
Dima Dzuba
 
Курсы по мобильной разработке под iOS. 5 лекция. Работа с данными
Курсы по мобильной разработке под iOS. 5 лекция. Работа с даннымиКурсы по мобильной разработке под iOS. 5 лекция. Работа с данными
Курсы по мобильной разработке под iOS. 5 лекция. Работа с даннымиГлеб Тарасов
 
AlgoCollections (RUS)
AlgoCollections (RUS)AlgoCollections (RUS)
AlgoCollections (RUS)
Anton Bukov
 
Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3
Яковенко Кирилл
 
2-е занятие курса iPhone разработки в ГУ-ВШЭ
2-е занятие курса iPhone разработки в ГУ-ВШЭ2-е занятие курса iPhone разработки в ГУ-ВШЭ
2-е занятие курса iPhone разработки в ГУ-ВШЭOleg Parinov
 
Александр Гранин, "Декларативно-функциональный дизайн на С++11"
Александр Гранин, "Декларативно-функциональный дизайн на С++11"Александр Гранин, "Декларативно-функциональный дизайн на С++11"
Александр Гранин, "Декларативно-функциональный дизайн на С++11"
Platonov Sergey
 
Функционально декларативный дизайн на C++
Функционально декларативный дизайн на C++Функционально декларативный дизайн на C++
Функционально декларативный дизайн на C++
Alexander Granin
 
Объектное и прототипное программирование в Javascript
Объектное и прототипное программирование в JavascriptОбъектное и прототипное программирование в Javascript
Объектное и прототипное программирование в Javascript
Denis Latushkin
 
Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...
Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...
Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...
CocoaHeads
 
Rambler.iOS #3: Test-Driven Development в iOS
Rambler.iOS #3: Test-Driven Development в iOSRambler.iOS #3: Test-Driven Development в iOS
Rambler.iOS #3: Test-Driven Development в iOS
RAMBLER&Co
 

Similar to Kvc, kvo (20)

msumobi2. Лекция 2
msumobi2. Лекция 2msumobi2. Лекция 2
msumobi2. Лекция 2
 
Школа-студия разработки приложений для iOS. Лекция 1. Objective-C
Школа-студия разработки приложений для iOS. Лекция 1. Objective-CШкола-студия разработки приложений для iOS. Лекция 1. Objective-C
Школа-студия разработки приложений для iOS. Лекция 1. Objective-C
 
Active Record for CoreData
Active Record for CoreDataActive Record for CoreData
Active Record for CoreData
 
Школа-студия разработки для iOS. Лекция 4. Работа с данными
Школа-студия разработки для iOS. Лекция 4. Работа с даннымиШкола-студия разработки для iOS. Лекция 4. Работа с данными
Школа-студия разработки для iOS. Лекция 4. Работа с данными
 
7 кашкута
7 кашкута7 кашкута
7 кашкута
 
Перспективы функционального подхода
Перспективы функционального подходаПерспективы функционального подхода
Перспективы функционального подхода
 
Курсы по мобильной разработке. 1 лекция. Знакомство с iOS
Курсы по мобильной разработке. 1 лекция. Знакомство с iOSКурсы по мобильной разработке. 1 лекция. Знакомство с iOS
Курсы по мобильной разработке. 1 лекция. Знакомство с iOS
 
Ecma script 6 in action
Ecma script 6 in actionEcma script 6 in action
Ecma script 6 in action
 
Solit 2014, EcmaScript 6 in Action, Трухин Юрий
Solit 2014, EcmaScript 6 in Action, Трухин Юрий Solit 2014, EcmaScript 6 in Action, Трухин Юрий
Solit 2014, EcmaScript 6 in Action, Трухин Юрий
 
Интуит. Разработка приложений для iOS. Лекция 8. Работа с данными
Интуит. Разработка приложений для iOS. Лекция 8. Работа с даннымиИнтуит. Разработка приложений для iOS. Лекция 8. Работа с данными
Интуит. Разработка приложений для iOS. Лекция 8. Работа с данными
 
Объектно-ориентированное программирование. Лекции 9 и 10
Объектно-ориентированное программирование. Лекции 9 и 10Объектно-ориентированное программирование. Лекции 9 и 10
Объектно-ориентированное программирование. Лекции 9 и 10
 
Курсы по мобильной разработке под iOS. 5 лекция. Работа с данными
Курсы по мобильной разработке под iOS. 5 лекция. Работа с даннымиКурсы по мобильной разработке под iOS. 5 лекция. Работа с данными
Курсы по мобильной разработке под iOS. 5 лекция. Работа с данными
 
AlgoCollections (RUS)
AlgoCollections (RUS)AlgoCollections (RUS)
AlgoCollections (RUS)
 
Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3Лекция #5. Введение в язык программирования Python 3
Лекция #5. Введение в язык программирования Python 3
 
2-е занятие курса iPhone разработки в ГУ-ВШЭ
2-е занятие курса iPhone разработки в ГУ-ВШЭ2-е занятие курса iPhone разработки в ГУ-ВШЭ
2-е занятие курса iPhone разработки в ГУ-ВШЭ
 
Александр Гранин, "Декларативно-функциональный дизайн на С++11"
Александр Гранин, "Декларативно-функциональный дизайн на С++11"Александр Гранин, "Декларативно-функциональный дизайн на С++11"
Александр Гранин, "Декларативно-функциональный дизайн на С++11"
 
Функционально декларативный дизайн на C++
Функционально декларативный дизайн на C++Функционально декларативный дизайн на C++
Функционально декларативный дизайн на C++
 
Объектное и прототипное программирование в Javascript
Объектное и прототипное программирование в JavascriptОбъектное и прототипное программирование в Javascript
Объектное и прототипное программирование в Javascript
 
Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...
Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...
Встреча №9. Алгоритмы и коллекции стандартных библиотек C++, C#, Java, Object...
 
Rambler.iOS #3: Test-Driven Development в iOS
Rambler.iOS #3: Test-Driven Development в iOSRambler.iOS #3: Test-Driven Development в iOS
Rambler.iOS #3: Test-Driven Development в iOS
 

More from Noveo

Гуманитарные специальности в IT-индустрии
Гуманитарные специальности в IT-индустрииГуманитарные специальности в IT-индустрии
Гуманитарные специальности в IT-индустрии
Noveo
 
Box model, display and position (HTML5 тема 07 - box model, display position)
Box model, display and position (HTML5 тема 07 - box model, display position)Box model, display and position (HTML5 тема 07 - box model, display position)
Box model, display and position (HTML5 тема 07 - box model, display position)
Noveo
 
Ссылки, списки и меню (HTML5 тема 06 - ссылки, списки и меню)
Ссылки, списки и меню (HTML5 тема 06 - ссылки, списки и меню)Ссылки, списки и меню (HTML5 тема 06 - ссылки, списки и меню)
Ссылки, списки и меню (HTML5 тема 06 - ссылки, списки и меню)
Noveo
 
Стилизация текста (HTML5 тема 05 - стилизация текста)
Стилизация текста (HTML5 тема 05 - стилизация текста)Стилизация текста (HTML5 тема 05 - стилизация текста)
Стилизация текста (HTML5 тема 05 - стилизация текста)
Noveo
 
Семантика текста (HTML5 тема 04 - семантика текста)
Семантика текста (HTML5 тема 04 - семантика текста)Семантика текста (HTML5 тема 04 - семантика текста)
Семантика текста (HTML5 тема 04 - семантика текста)
Noveo
 
Основы CSS (HTML5 тема 02 - основы CSS)
Основы CSS (HTML5 тема 02 - основы CSS)Основы CSS (HTML5 тема 02 - основы CSS)
Основы CSS (HTML5 тема 02 - основы CSS)
Noveo
 
Структура HTML документа (HTML5 тема 01 - структура html документа)
Структура HTML документа (HTML5 тема 01 - структура html документа)Структура HTML документа (HTML5 тема 01 - структура html документа)
Структура HTML документа (HTML5 тема 01 - структура html документа)
Noveo
 
Yii2
Yii2Yii2
Yii2
Noveo
 
Сессии и авторизация
Сессии и авторизацияСессии и авторизация
Сессии и авторизация
Noveo
 
Rest
RestRest
Rest
Noveo
 
PHP basic
PHP basicPHP basic
PHP basic
Noveo
 
PHP Advanced
PHP AdvancedPHP Advanced
PHP Advanced
Noveo
 
PHP and MySQL
PHP and MySQLPHP and MySQL
PHP and MySQL
Noveo
 
MySQL
MySQLMySQL
MySQL
Noveo
 
Push Notifications (Lecture 22 – push notifications)
Push Notifications (Lecture 22 – push notifications)Push Notifications (Lecture 22 – push notifications)
Push Notifications (Lecture 22 – push notifications)
Noveo
 
RxJava+RxAndroid (Lecture 20 – rx java)
RxJava+RxAndroid (Lecture 20 – rx java)RxJava+RxAndroid (Lecture 20 – rx java)
RxJava+RxAndroid (Lecture 20 – rx java)
Noveo
 
Работа с соцсетями (Lecture 19 – social)
Работа с соцсетями (Lecture 19 – social)Работа с соцсетями (Lecture 19 – social)
Работа с соцсетями (Lecture 19 – social)
Noveo
 
Работа с геоданными (Lecture 18 – geolocation)
Работа с геоданными (Lecture 18 – geolocation)Работа с геоданными (Lecture 18 – geolocation)
Работа с геоданными (Lecture 18 – geolocation)
Noveo
 
Animations (Lecture 17 – animations)
Animations (Lecture 17 – animations)Animations (Lecture 17 – animations)
Animations (Lecture 17 – animations)
Noveo
 
Toolbar (Lecture 16 – toolbar)
Toolbar (Lecture 16 – toolbar)Toolbar (Lecture 16 – toolbar)
Toolbar (Lecture 16 – toolbar)
Noveo
 

More from Noveo (20)

Гуманитарные специальности в IT-индустрии
Гуманитарные специальности в IT-индустрииГуманитарные специальности в IT-индустрии
Гуманитарные специальности в IT-индустрии
 
Box model, display and position (HTML5 тема 07 - box model, display position)
Box model, display and position (HTML5 тема 07 - box model, display position)Box model, display and position (HTML5 тема 07 - box model, display position)
Box model, display and position (HTML5 тема 07 - box model, display position)
 
Ссылки, списки и меню (HTML5 тема 06 - ссылки, списки и меню)
Ссылки, списки и меню (HTML5 тема 06 - ссылки, списки и меню)Ссылки, списки и меню (HTML5 тема 06 - ссылки, списки и меню)
Ссылки, списки и меню (HTML5 тема 06 - ссылки, списки и меню)
 
Стилизация текста (HTML5 тема 05 - стилизация текста)
Стилизация текста (HTML5 тема 05 - стилизация текста)Стилизация текста (HTML5 тема 05 - стилизация текста)
Стилизация текста (HTML5 тема 05 - стилизация текста)
 
Семантика текста (HTML5 тема 04 - семантика текста)
Семантика текста (HTML5 тема 04 - семантика текста)Семантика текста (HTML5 тема 04 - семантика текста)
Семантика текста (HTML5 тема 04 - семантика текста)
 
Основы CSS (HTML5 тема 02 - основы CSS)
Основы CSS (HTML5 тема 02 - основы CSS)Основы CSS (HTML5 тема 02 - основы CSS)
Основы CSS (HTML5 тема 02 - основы CSS)
 
Структура HTML документа (HTML5 тема 01 - структура html документа)
Структура HTML документа (HTML5 тема 01 - структура html документа)Структура HTML документа (HTML5 тема 01 - структура html документа)
Структура HTML документа (HTML5 тема 01 - структура html документа)
 
Yii2
Yii2Yii2
Yii2
 
Сессии и авторизация
Сессии и авторизацияСессии и авторизация
Сессии и авторизация
 
Rest
RestRest
Rest
 
PHP basic
PHP basicPHP basic
PHP basic
 
PHP Advanced
PHP AdvancedPHP Advanced
PHP Advanced
 
PHP and MySQL
PHP and MySQLPHP and MySQL
PHP and MySQL
 
MySQL
MySQLMySQL
MySQL
 
Push Notifications (Lecture 22 – push notifications)
Push Notifications (Lecture 22 – push notifications)Push Notifications (Lecture 22 – push notifications)
Push Notifications (Lecture 22 – push notifications)
 
RxJava+RxAndroid (Lecture 20 – rx java)
RxJava+RxAndroid (Lecture 20 – rx java)RxJava+RxAndroid (Lecture 20 – rx java)
RxJava+RxAndroid (Lecture 20 – rx java)
 
Работа с соцсетями (Lecture 19 – social)
Работа с соцсетями (Lecture 19 – social)Работа с соцсетями (Lecture 19 – social)
Работа с соцсетями (Lecture 19 – social)
 
Работа с геоданными (Lecture 18 – geolocation)
Работа с геоданными (Lecture 18 – geolocation)Работа с геоданными (Lecture 18 – geolocation)
Работа с геоданными (Lecture 18 – geolocation)
 
Animations (Lecture 17 – animations)
Animations (Lecture 17 – animations)Animations (Lecture 17 – animations)
Animations (Lecture 17 – animations)
 
Toolbar (Lecture 16 – toolbar)
Toolbar (Lecture 16 – toolbar)Toolbar (Lecture 16 – toolbar)
Toolbar (Lecture 16 – toolbar)
 

Kvc, kvo

  • 3. Key-Value mechanism KVC — механизм, позволяющий обращаться к свойствам объекта, используя строковые идентификаторы — ключи (Key). Ключи можно выстраивать в цепочку (KeyPath), обращаясь к вложенным свойствам. KVC основывается на методах протокола NSKeyValueCoding . Это позволяет решить во время выполнения к какому свойству обратиться. NSString *valueB = [myObject valueForKey:@"someString"]; NSString *valueC = [myObject valueForKeyPath:@"parentObject.someString"]; Key-Value Coding
  • 4. Key-Value mechanism @interface Person : NSObject @property (strong, nonatomic) NSString *name; @property (strong, nonatomic) NSNumber *age; //... @end { [ "name": "Alice", "age": 22, ... ], [ "name": "Bob", "age": 24, ... ] } Нужно создать массив объектов Person из полученного JSON Key-Value Coding
  • 5. Key-Value mechanism Key-Value Coding NSArray *personsDescriptions = /*...*/; NSMutableArray *persons = /*...*/; // Вручную работаем с каждым свойством for (NSDictionary *personDescription in personsDescriptions) { Person *person = [[Person alloc] init]; person.name = personDescription[@"name"]; person.age = personDescription[@"age"]; //... }
  • 6. Key-Value mechanism Key-Value Coding NSArray *personsDescriptions = /*...*/; NSMutableArray *persons = /*...*/; // Вручную работаем с каждым свойством for (NSDictionary *personDescription in personsDescriptions) { Person *person = [[Person alloc] init]; person.name = personDescription[@"name"]; person.age = personDescription[@"age"]; //... } // Автоматический проход по всем свойствам for (NSDictionary *personDescription in personsDescriptions) { Person *person = [[Person alloc] init]; for (NSString *key in personDescription.allKeys) { [person setValue:personDescription[key] forKey:key]; } }
  • 7. Key-Value mechanism Key-Value Coding NSArray *personsDescriptions = /*...*/; NSMutableArray *persons = /*...*/; // Вручную работаем с каждым свойством for (NSDictionary *personDescription in personsDescriptions) { Person *person = [[Person alloc] init]; person.name = personDescription[@"name"]; person.age = personDescription[@"age"]; //... } // Автоматический проход по всем свойствам for (NSDictionary *personDescription in personsDescriptions) { Person *person = [[Person alloc] init]; for (NSString *key in personDescription.allKeys) { [person setValue:personDescription[key] forKey:key]; } } Нужна осторожность: только мы отвечаем за правильность ключей.
  • 8. Key-Value mechanism KVC позволяет включать в качестве ключей в KeyPath не только объекты, но и коллекции объектов. На выходе мы получим коллекцию, аггрегирующую значения заданного поля у всех элементов коллекции. @interface Person : NSObject @property (strong, nonatomic) NSString *name; @property (strong, nonatomic) NSNumber *age; //... @end //... @property (strong, nonatomic) NSArray *myPersons; //... NSArray *allNames = [self valueForKeyPath:@"myPersons.name"]; Key-Value Coding
  • 9. Key-Value mechanism KVC предоставляет несколько операторов для обработки значений элементов коллекции: @avg, @max, @min, @distinctUnionOfObjects и др. @interface Person : NSObject @property (strong, nonatomic) NSString *name; @property (strong, nonatomic) NSNumber *age; //... @end //... @property (strong, nonatomic) NSArray *myPersons; //... NSArray *avgAge = [self valueForKeyPath:@"myPersons.@avg.age"]; Key-Value Coding
  • 10. Key-Value mechanism NSPredicate позволяет делать достаточно хитрые запросы (с фильтрами и выражениями), в том числе при доступе к значениям через KVC. Синтаксис выражений похож на SQL запросы и может использовать регулярные выражения. @interface Person : NSObject @property (strong, nonatomic) NSString *name; @property (strong, nonatomic) NSNumber *age; //... @end //... NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name CONTAINS 'Bob'"]; NSLog(@"Bobs: %@", [people filteredArrayUsingPredicate:predicate]); NSPredicate
  • 11. Key-Value mechanism По умолчанию обращение по несуществующему ключу вызывает исключение, поэтому нужно реализовать одну из политик: ● Следить за тем, что мы не обращаемся к несуществующим ключам ● Переопределить методы, обрабатывающие обращение к несуществующим ключам (valueForUndefinedKey: и setValue: forUndefinedKey: ) Значения при использовании KVC имеют тип id, поэтому: ● При обращении к скаляру (BOOL, int, float, ...) через KVC, он автоматически оборачивается в NSNumber. ● При обращении к структуре (struct) через KVC, она автоматически оборачивается в NSValue. ● При присваивании значения nil скаляру через KVC, вызывается метод setNilValueForKey: , в котором нужно определить желаемое поведение. Key-Value Coding
  • 12. Key-Value mechanism Для поддержки работы KVC нужно правильно именовать методы-акцессоры: ● Имя геттера должно совпадать с именем свойства ● Имя сеттера должно иметь префикс set @property (strong, nonatomic) NSString *name; //... - (NSString *)name {...} - (void)setName:(NSString *)name {...} Key-Value Coding
  • 13. Key-Value mechanism Key-Value Coding Чтобы обеспечить поддержку KVC/KVO для свойства, нужно соблюдать правила руководства по KVC compliance. По умолчанию свойства стандартных классов нельзя считать KVC-совместимыми, а документация явно указывает какие свойства обладают этим свойством.
  • 14. Key-Value mechanism KVO — механизм поверх KVC, реализующий автоматическую нотификацию объекта об изменениях значений свойств (в общем случае) другого объекта. (паттерн Observer) Объект, который хочет получать такие нотификации должен: ● Подписаться на нотификации, указав получателя, объект и KeyPath для отслеживания, свой контекст, дополнительные опции (например нотификация до или после изменения значения). ● Обрабатывать полученные нотификации, проверив что они действительно должны быть обработаны. (Родительский класс мог так же подписаться на нотификации и их нужно передать в super). ● По необходимости или в конце жизненного цикла отписаться от всех ранее созданных подписок. Key-Value Observing
  • 15. Key-Value mechanism KVO — мощный механизм, который не терпит ошибок… Key-Value Observing
  • 16. Key-Value mechanism ● Создаём контекст. Он помогает определить, принадлежат ли нам полученные нотификации. static void *const myContext = (void *)&myContext; ● Подписываемся на изменения значений. (например в init) [self.myPerson addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:myContext]; ● Отписываемся от нотификаций. (например в dealloc) [self.myPerson removeObserver:self forKeyPath:@"name" context:myContext]; Key-Value Observing
  • 17. Key-Value mechanism ● Получаем и обрабатываем нотификации. - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (context == myContext) { Person *person = (Person *)object; NSLog(@"New value is %@.", person.name); } else { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } Key-Value Observing
  • 18. Key-Value mechanism KVO поддерживает свойства, не имеющие под собой ivar, например для которых значение вычисляется каждый раз в геттере. @property (copy, nonatomic) NSString *firstName; @property (copy, nonatomic) NSString *lastName; @property (readonly, nonatomic) NSString *fullName; - (NSString *)fullName { return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName]; } Key-Value Observing
  • 19. Key-Value mechanism KVO поддерживает свойства, не имеющие под собой ivar, например для которых значение вычисляется каждый раз в геттере. + (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key { NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key]; if ([key isEqualToString:@"fullName"]) { NSArray *affectingKeys = @[@"lastName", @"firstName"]; keyPaths = [keyPaths setByAddingObjectsFromArray:affectingKeys]; } return keyPaths; } Key-Value Observing
  • 20. Key-Value mechanism ● Нотификации от всех объектов и всех KeyPath приходят в один обработчик. ● Если мы переименовали свойство, мы ответственны за обновление всех строк с KeyPath, куда это свойство входило. ● Каждый объект должен обрабатывать все те и только те нотификации, на которые он подписан. (Нельзя отдавать в super свою нотификацию, не стоит обрабатывать нотификации, предназначенные для super.) ● Нельзя не отписываться от нотификаций, на которые мы подписались. ● Нельзя отписываться дважды от одной и той же нотификации. ● Нельзя проверить подписан ли объект на ту или иную нотификацию. ● Если кто-то использует свойство для KVO, к нему нельзя обращаться через ivar, или нужно вручную нотифицировать об изменении значения (willChangeValueForKey: / didChangeValueForKey:). ● KVO с трудом поддерживает отслеживание изменений внутри коллекции. Key-Value Observing
  • 21. Key-Value mechanism Для избавления от страданий создано много вариантов обёрток, скрывающих API KVO. ● ReactiveCocoa [RACObserve(model, keyname) subscribeNext:^(NSString *newValue) { //... }]; ● KVOBlocks [model addObserver:self forKeyPath::@"keyname" options:NSKeyValueObservingOptionNew context:nil withBlock:^(NSDictionary *change, void *context) { //... }]; Key-Value Observing