Знакомство с ReactiveCocoa

от автора

RACSignal

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

Пример 1. Сигнал, наблюдающий свойство name и передающий значения в блок:

User *user = [User new];      RACSignal *userNameSignal = RACObserve(user, name);      [userNameSignal subscribeNext:^(NSString *newValue) {         NSLog(@"New value: %@", newValue); }];      user.name = @"ivan";  //Вывод в консоли: //New value: ivan 

Преобразование сигналов

До того, как новое значение объекта дойдет до подписчика, оно может быть подвергнуто различным преобразованиям. Такими как:

  • изменение значения (map)
  • фильтрация (filter, ignore)
  • объединение с другим значением (combine)
  • упрощение нескольких сигналов в одно (reduce)

Пример 2. Продолжая первый пример, изменим передаваемое значение:

User *user = [User new];      RACSignal *userNameSignal = RACObserve(user, name);      [[userNameSignal map:^id(NSString *newValue) {         return newValue.capitalizedString; }] subscribeNext:^(NSString *newValue) {         NSLog(@"New value: %@", newValue); }];      user.name = @"ivan";  //Теперь все значения будут передаваться подписчикам с большой буквы. //Вывод в консоли: //New value: Ivan 

Биндинги

Преобразования не были бы так полезны, если бы не биндинги. Они позволяют создать зависимость одного свойства от другого:

  • Кнопка авторизации активна только если введены логин и пароль
  • Поля ввода логина и пароля отключены, когда происходит авторизация
  • Свойство user.isValidName меняется автоматически когда меняется свойство user.name.

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

Продолжая предыдущий пример, сделаем биндинг для свойства user.login, чтобы подходящий логин автоматически предлагался пользователю на основе имени:

RAC(user, login) = [userNameSignal map:^id(NSString *name) {         return [name stringByReplacingOccurrencesOfString:@" " withString:@"_"].lowercaseString; }];      user.name = @"Vladimir Petrov";      NSLog(@"Login: %@", user.login);  // Вывод в консоли: // Login: vladimir_petrov 

Минусы

Начав использовать ReactiveCocoa, уже трудно представить разработку без него. Но у этого фреймворка есть минусы, которые для кого-то могут быть существенными:

  • Частое использование KVO может снизить производительность. Решается оптимизацией и неиспользованием RAC’a в высоконагруженных участках кода.
  • Сложная отладка из-за частого использования блоков, особенно внутри самого ReactiveCocoa. Порой в поиске ошибки помогает лишь интуитивное понимание objective-c.
  • Легко допустить ошибку и они приводят к неожиданным последствиям.
  • Перегруженный синтаксис. Этой проблемы не будет с переходом на swift.

В заключение

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

ссылка на оригинал статьи http://habrahabr.ru/post/248771/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *