ReactiveCocoa use detailed 01

ReactiveCocoa use detailed 01

ReactiveCocoa (referred to as RAC) is an Githubopen source functional reactive programming framework for iOS and OS development. It provides a series of APIs for combining and transforming value streams.

1. What is Responsive Turning into Thought?

Before learning a framework, you must first understand the programming idea of ​​this framework. Before introducing the idea of ​​reactive programming, let's first introduce the programming ideas that you have come into contact with before.

1. Object Oriented

  • everything is an object
    • It is a kind of programming language with objects as the basic program structure unit
    • Typical object-oriented programming languages ​​are C++, C#, Javaetc.

2. Process Oriented

  • A process-centric programming idea
  • C is a procedural language

3. Chain programming idea

  • It is to link multiple operations (multi-line code) together through a dot (.) to form a code, which makes the code more readable.
  • Chain programming features: the return value of the method is block, the block must have a return value (the object itself), and block parameters (the value that needs to be manipulated)
  • Typical framework: masonry framework.

4. Functional programming ideas

  • everything is flow
    • You don't need to consider the calling order, you just need to know the result
    • Similar to the butterfly effect, generating an event will affect many things, these events will spread out like a stream, and then affect the result
    • Representative: KVO application

5. Functional programming ideas

  • It is to write the operation as a series of nested functions or method calls as much as possible
  • Features: Each method must have a return value (its own object), take a function or block as a parameter, block parameter (value that needs to be operated) and block return value (operation result)
  • Representative: ReactiveCocoa

6. ReactiveCocoaProgramming ideas

  • functional programmingFunctional Programming
  • reactive programmingReactive Programming

Therefore, ReactiveCocoadescribed as a functional reactive programming (FRP) framework, RACsome common classes are described below in detail

2. RACSiganl signal class

  • ReactiveCocoaOne of the most central concepts in RACStream. RACStreamThere are two subclasses - RACSignaland RACSequence; here we mainly talk about RACSignal;
  • In ReactiveCocoathe entire library, it RACSignaloccupies a relatively important position, and RACSignalthe transformation operation is one of the RACStreamcores of the entire stream operation.
  • Let's take a look at RACSignalthe complete process of being subscribed
- (void)test2 {
    //创建信号
    RACSignal *single = [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        //发送消息
        [subscriber sendNext:@"a"];
        [subscriber sendNext:@"b"];
        //发送完成
        [subscriber sendCompleted];

        //清空数据
        return [RACDisposable disposableWithBlock:^{
            //当订阅者被消耗的时候就会执行
            //当订阅者发送完成,或者error的时候也会执行
            NSLog(@"RACDisposable的block");
        }];
    }];

    //订阅信号
    RACDisposable *disposable = [single subscribeNext:^(id  _Nullable x) {
        NSLog(@"value = %@", x);
    } error:^(NSError * _Nullable error) {
        NSLog(@"error: %@", error);
    } completed:^{
        NSLog(@"completed");
    }];

    //释放
    [disposable dispose];
}
  • RACSignalSome subclasses to look at before
    • RACDynamicSignal: Dynamic signal, using a blockto implement subscription behavior, we create an instance of this class when we use RACSignalthe +createSignal:method of
    • RACEmptySignal: empty signal, RACSignalthe +emptymethod used to implement ;
    • RACReturnSignal: Unary signal, RACSignalthe +return:method used to implement ;
    • RACErrorSignal: error signal, RACSignalthe +error:method used to implement ;
    • RACChannelTerminal: Channel terminal, RACChannelrepresenting a terminal of , used to realize two-way binding

RACSignalRACDynamicSignalWhen creating a signal, the underlying createSignalmethod will be called, as follows:

+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe {
    return [RACDynamicSignal createSignal:didSubscribe];
}

The block here is a id<RACSubscriber>type subscriber, and this RACSubscriber, we can click in to see some underlying implementations, the protocol methods are as follows:

@protocol RACSubscriber <NSObject>
@required

/// Sends the next value to subscribers.
- (void)sendNext:(nullable id)value;

/// Sends the error to subscribers.
- (void)sendError:(nullable NSError *)error;

/// Sends completed to subscribers.
- (void)sendCompleted;

/// Sends the subscriber a disposable that represents one of its subscriptions.
- (void)didSubscribeWithDisposable:(RACCompoundDisposable *)disposable;
  • The underlying implementation of RACSignal:
    • 1. Create a signal, first didSubscribesave it to the signal, it will not trigger.
    • 2. When the signal is subscribed, it is signalcalledsubscribeNext:nextBlock
    • 2.1 subscribeNextSubscribers will be created internally subscriberand nextBlocksaved to subscriber.
    • 2.2 subscribeNextwill be called internallysiganl的didSubscribe
    • 2.3 When the signal subscription is completed and data is not sent, it is best to call the completed sending[subscriber sendCompleted];
    • [RACDisposable disposable]When the subscription is completed, the unsubscribe signal will be automatically called internally
    • 3. siganlThe didSubscribemiddle call[subscriber sendNext:@1];
    • 3.1 The sendNextbottom layer is actually executedsubscribernextBlock

3. Signal provider:RACSubject

  • A signal provider, which can act as a signal and send a signal
  • Subscribe first, then send signals
  • Usage scenario: usually used instead of proxy/notification

1. RACSubjectSimple to use

- (void)setRacSubject1 {
    //先订阅, 在发送信号
    //1. 创建信号
    RACSubject *subject = [RACSubject subject];

    //2. 订阅
    //内部创建RACSubscriber
    [subject subscribeNext:^(id  _Nullable x) {
        NSLog(@"第一个订阅者--%@", x);
    }];

    [subject subscribeNext:^(id  _Nullable x) {
        NSLog(@"第二个订阅者---%@", x);
    }];

    //3. 发送信号
    //遍历所有的订阅者, 执行nextBlock
    [subject sendNext:@2];

    /** 打印结果
     2018-03-17 20:18:19.782119+0800 ReactiveObjc[23883:1420936] 第一个订阅者--2
     2018-03-17 20:18:19.784715+0800 ReactiveObjc[23883:1420936] 第二个订阅者---2
     */
}
  • RACSubject: The underlying implementation is different from RACSignal
    • 1. Call subscribeNextthe subscription signal, just save the subscriber, and the subscriber's nextBlockvalue has been assigned.
    • 2. Call sendNextthe send signal, traverse all the subscribers just saved, and call the subscribers one by onenextBlock

2. RACReplaySubjectSimple to use

  • Repeatedly provide the signal class, a subclass of RACSubject
  • Send the signal first, then subscribe to the signal;
  • scenes to be used
      1. If a signal is subscribed once, it needs to send the previous value repeatedly, and use repeat to provide the signal class.
      1. The number can be set capacityto limit valuethe number of caches, that is, only the latest values ​​can be buffered
- (void)setReplaySubject {
    //创建信号
    RACReplaySubject *replySub = [RACReplaySubject subject];

    //发送信号
    [replySub sendNext:@23];
    [replySub sendNext:@34];

    //订阅信号
    // 遍历值,让一个订阅者去发送多个值
    // 只要订阅一次,之前所有发送的值都能获取到.
    [replySub subscribeNext:^(id  _Nullable x) {
        NSLog(@"%@", x);
    }];

    /**
     2018-03-19 12:01:14.112253+0800 ReactiveObjc[5130:446958] 23
     2018-03-19 12:01:14.112511+0800 ReactiveObjc[5130:446958] 34
     */
}
  • RACReplaySubjectThe underlying implementation of
      1. When subscribing to a signal, the subscriber is saved internally, and the subscriber responds to the block
      1. When the signal is sent, it traverses the subscribers and calls the subscriber's nextBlock
      1. The sent signal will be saved. When the subscriber subscribes to the signal, the previously saved signal will act on the new subscriber one by one. The capacity of the saved signal is capacitydetermined, which is also different from RACSubject.

3. Alternative Agents/Notices

  • Here we imagine a scenario of reverse value transfer, there is a custom view in vc, when clicked View, change the background color of vc
  • Usually what we do is to use proxy/notify/block

3-1. Let's take a look at the simple use of the proxy

Set protocol in custom View

#import <UIKit/UIKit.h>

@class SubjectView;
@protocol SubjectDelegate <NSObject>

@optional
- (void)viewWithTap:(SubjectView *)subView;

@end

@interface SubjectView : UIView

@property (nonatomic, weak) id<SubjectDelegate> delegate;


@end

In vc, follow the proxy, and implement the proxy method

/// 代理方法
-(void)viewWithTap:(SubjectView *)subView{
    NSLog(@"完成代理, 点击了view");

    UIColor *color = [UIColor colorWithRed:(arc4random() % 255) / 255.0 green:(arc4random() % 255) / 255.0 blue:(arc4random() % 255) / 255.0 alpha:1.0];
    self.view.backgroundColor = color;
}

3-1. RACSubjectIn lieu of proxy

in custom SubjectView.hfile

#import <UIKit/UIKit.h>
#import <ReactiveObjC.h>

@interface SubjectView : UIView

@property (nonatomic, strong) RACSubject *subject;

@end

in custom SubjectView.mfile

#import "SubjectView.h"

@implementation SubjectView

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    //发送信号
    [_subject sendNext:self];
}

@end

Let's take a look at the operation in vc

- (void)setupSubjectView {
    SubjectView *subV = [[SubjectView alloc]init];
    subV.backgroundColor = [UIColor redColor];
    subV.frame = CGRectMake(100, 100, 100, 100);
    RACSubject *subject = [RACSubject subject];
    [subject subscribeNext:^(id  _Nullable x) {
        NSLog(@"完成代理, 点击了view");

        UIColor *color = [UIColor colorWithRed:(arc4random() % 255) / 255.0 green:(arc4random() % 255) / 255.0 blue:(arc4random() % 255) / 255.0 alpha:1.0];
        self.view.backgroundColor = color;
    }];
    subV.subject = subject;
    [self.view addSubview:subV];
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325898717&siteId=291194637