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

в 13:20, , рубрики: iOS, reactivecocoa, разработка под iOS

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

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

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

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

  • изменение значения (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

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

Биндинги

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

  • Кнопка авторизации активна только если введены логин и пароль
  • Поля ввода логина и пароля отключены, когда происходит авторизация
  • Свойство 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 - 3

Минусы

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

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

В заключение

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

Автор: lostuser

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js