RAC的冷信號和熱信號-RACSubject

RAC的冷信號和熱信號

本篇目錄

  1. 何為冷信號,熱信號;
  2. 為何會有RACSubject這個類的存在;
  3. RACSubject已經(jīng)其子類的介紹;
  4. 如何將一個冷信號轉(zhuǎn)成熱信號。

何為冷信號,熱信號?

冷信號:

RAC中的RACSiganl類中幾乎都是冷信號,以+ (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe方法為例:

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

初始化一個RACDynamicSignal保存一個block,等到有訂閱者去訂閱,如果沒有訂閱者的話,一直不會被調(diào)用,也就是冷信號被調(diào)用的前提是要有訂閱者,這就是冷信號;

熱信號:

解釋完冷信號,那熱信號肯定是即使沒有訂閱者也是會發(fā)送消息的,是的rac提供了RACSubject,專門處理熱信號的。

為何會有RACSubject這個類的存在?

要想解釋為什么會存在RACSubject這個類,首先來一個場景

 self.sessionManager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:@"http://api.xxxx.com"]];

    self.sessionManager.requestSerializer = [AFJSONRequestSerializer serializer];
    self.sessionManager.responseSerializer = [AFJSONResponseSerializer serializer];

    @weakify(self)
    RACSignal *fetchData = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        @strongify(self)
        NSURLSessionDataTask *task = [self.sessionManager GET:@"fetchData" parameters:@{@"someParameter": @"someValue"} success:^(NSURLSessionDataTask *task, id responseObject) {
            [subscriber sendNext:responseObject];
            [subscriber sendCompleted];
        } failure:^(NSURLSessionDataTask *task, NSError *error) {
            [subscriber sendError:error];
        }];
        return [RACDisposable disposableWithBlock:^{
            if (task.state != NSURLSessionTaskStateCompleted) {
                [task cancel];
            }
        }];
    }];

    RACSignal *title = [fetchData flattenMap:^RACSignal *(NSDictionary *value) {
        if ([value[@"title"] isKindOfClass:[NSString class]]) {
            return [RACSignal return:value[@"title"]];
        } else {
            return [RACSignal error:[NSError errorWithDomain:@"some error" code:400 userInfo:@{@"originData": value}]];
        }
    }];

    RACSignal *desc = [fetchData flattenMap:^RACSignal *(NSDictionary *value) {
        if ([value[@"desc"] isKindOfClass:[NSString class]]) {
            return [RACSignal return:value[@"desc"]];
        } else {
            return [RACSignal error:[NSError errorWithDomain:@"some error" code:400 userInfo:@{@"originData": value}]];
        }
    }];

    RACSignal *renderedDesc = [desc flattenMap:^RACStream *(NSString *value) {
        NSError *error = nil;
        RenderManager *renderManager = [[RenderManager alloc] init];
        NSAttributedString *rendered = [renderManager renderText:value error:&error];
        if (error) {
            return [RACSignal error:error];
        } else {
            return [RACSignal return:rendered];
        }
    }];

    RAC(self.someLablel, text) = [[title catchTo:[RACSignal return:@"Error"]]  startWith:@"Loading..."];
    RAC(self.originTextView, text) = [[desc catchTo:[RACSignal return:@"Error"]] startWith:@"Loading..."];
    RAC(self.renderedTextView, attributedText) = [[renderedDesc catchTo:[RACSignal return:[[NSAttributedString alloc] initWithString:@"Error"]]] startWith:[[NSAttributedString alloc] initWithString:@"Loading..."]];

我們再開發(fā)中經(jīng)常會根據(jù)服務(wù)器返回的數(shù)據(jù)解析不同的字段進(jìn)行不同的操作,上面寫的情況在開發(fā)中很常見,如果用Charles抓取的話,其實發(fā)送了3次請求,都知道這個很不好,我們來分析一下為什么會調(diào)用3次呢,我們知道在下面三行代碼執(zhí)行前

 RAC(self.someLablel, text) = [[title catchTo:[RACSignal return:@"Error"]]  startWith:@"Loading..."];
    RAC(self.originTextView, text) = [[desc catchTo:[RACSignal return:@"Error"]] startWith:@"Loading..."];
    RAC(self.renderedTextView, attributedText) = [[renderedDesc catchTo:[RACSignal return:[[NSAttributedString alloc] initWithString:@"Error"]]] startWith:[[NSAttributedString alloc] initWithString:@"Loading..."]];

fetchData、title、desc、renderedDesc都是冷信號,當(dāng)調(diào)用上面三行代碼的時候fetchData、title、descrenderedDesc都變成了熱信號了,而title、descrenderedDesc信號內(nèi)部都對fetchData信號進(jìn)行了訂閱,從而導(dǎo)致源信號被訂閱了3次,而實際上我們只要發(fā)送一次網(wǎng)絡(luò)請求就可以了,即對源信號只有訂閱一次就夠了。

那我們?nèi)绾巫龅綄υ葱盘栔挥嗛喴淮文兀?code>RACSubject的存在就是解決這個問題的。

RACSubject閃亮登場

借用一下美團(tuán)團(tuán)隊提供的一個例子

 RACSubject *subject = [RACSubject subject];
    RACSubject *replaySubject = [RACReplaySubject subject];

    [[RACScheduler mainThreadScheduler] afterDelay:0.1 schedule:^{
        // Subscriber 1
        [subject subscribeNext:^(id x) {
            NSLog(@"Subscriber 1 get a next value: %@ from subject", x);
        }];
        [replaySubject subscribeNext:^(id x) {
            NSLog(@"Subscriber 1 get a next value: %@ from replay subject", x);
        }];

        // Subscriber 2
        [subject subscribeNext:^(id x) {
            NSLog(@"Subscriber 2 get a next value: %@ from subject", x);
        }];
        [replaySubject subscribeNext:^(id x) {
            NSLog(@"Subscriber 2 get a next value: %@ from replay subject", x);
        }];
    }];

    [[RACScheduler mainThreadScheduler] afterDelay:1 schedule:^{
        [subject sendNext:@"send package 1"];
        [replaySubject sendNext:@"send package 1"];
    }];

    [[RACScheduler mainThreadScheduler] afterDelay:1.1 schedule:^{
        // Subscriber 3
        [subject subscribeNext:^(id x) {
            NSLog(@"Subscriber 3 get a next value: %@ from subject", x);
        }];
        [replaySubject subscribeNext:^(id x) {
            NSLog(@"Subscriber 3 get a next value: %@ from replay subject", x);
        }];

        // Subscriber 4
        [subject subscribeNext:^(id x) {
            NSLog(@"Subscriber 4 get a next value: %@ from subject", x);
        }];
        [replaySubject subscribeNext:^(id x) {
            NSLog(@"Subscriber 4 get a next value: %@ from replay subject", x);
        }];
    }];

    [[RACScheduler mainThreadScheduler] afterDelay:2 schedule:^{
        [subject sendNext:@"send package 2"];
        [replaySubject sendNext:@"send package 2"];
    }];

輸出

2017-07-03 18:16:02.811 TestObjectProduct[90499:11197356] Subscriber 1 get a next value: send package 1 from subject
2017-07-03 18:16:02.812 TestObjectProduct[90499:11197356] Subscriber 2 get a next value: send package 1 from subject
2017-07-03 18:16:02.812 TestObjectProduct[90499:11197356] Subscriber 1 get a next value: send package 1 from replay subject
2017-07-03 18:16:02.813 TestObjectProduct[90499:11197356] Subscriber 2 get a next value: send package 1 from replay subject
2017-07-03 18:16:02.923 TestObjectProduct[90499:11197356] Subscriber 3 get a next value: send package 1 from replay subject
2017-07-03 18:16:02.923 TestObjectProduct[90499:11197356] Subscriber 4 get a next value: send package 1 from replay subject
2017-07-03 18:16:03.911 TestObjectProduct[90499:11197356] Subscriber 1 get a next value: send package 2 from subject
2017-07-03 18:16:03.911 TestObjectProduct[90499:11197356] Subscriber 2 get a next value: send package 2 from subject
2017-07-03 18:16:03.912 TestObjectProduct[90499:11197356] Subscriber 3 get a next value: send package 2 from subject
2017-07-03 18:16:03.912 TestObjectProduct[90499:11197356] Subscriber 4 get a next value: send package 2 from subject
2017-07-03 18:16:03.912 TestObjectProduct[90499:11197356] Subscriber 1 get a next value: send package 2 from replay subject
2017-07-03 18:16:03.912 TestObjectProduct[90499:11197356] Subscriber 2 get a next value: send package 2 from replay subject
2017-07-03 18:16:03.912 TestObjectProduct[90499:11197356] Subscriber 3 get a next value: send package 2 from replay subject
2017-07-03 18:16:03.913 TestObjectProduct[90499:11197356] Subscriber 4 get a next value: send package 2 from replay subject

解釋一下這個結(jié)果

  1. 先分別創(chuàng)建兩個信號對象RACSubjectRACReplaySubject,0.1s分別有兩個訂閱者分別對其訂閱;

  2. 1s后發(fā)送消息,

    1. 對于subject

      有兩個訂閱者Subscriber 1Subscriber 2,所以會先給訂閱者發(fā)送消息從而有

        ```
        2017-07-03 18:16:02.811 TestObjectProduct[90499:11197356] Subscriber 1 get a next value: send package 1 from subject
        2017-07-03 18:16:02.812 TestObjectProduct[90499:11197356] Subscriber 2 get a next value: send package 1 from subject
        ```
        `subject`內(nèi)部有個數(shù)組會保存訂閱者,也就是此時`subject`內(nèi)部已經(jīng)有了2個訂閱者了
        
2. 對于 `replaySubject`

       也有兩個訂閱者`Subscriber 1`和`Subscriber 2`,但是她和`subject`不同,它在訂閱的時候會首先判斷內(nèi)部之前有沒有發(fā)送過值,如果有則發(fā)送給訂閱者
   
        ```
        2017-07-03 18:16:02.812 TestObjectProduct[90499:11197356] Subscriber 1 get a next value: send package 1 from replay subject
        2017-07-03 18:16:02.813 TestObjectProduct[90499:11197356] Subscriber 2 get a next value: send package 1 from replay subject
        
        ```     
        發(fā)完以后,`replaySubject`的內(nèi)部會保存發(fā)送的值,也就是`send package 1`,且有兩個訂閱者。
        
        相信到這里大家沒什么問題
  1. 1.1s后又多了兩個訂閱者,Subscriber 3Subscriber 4;

    1. 對于subject,只是保存訂閱者;

    2. 而當(dāng)程序走到下面這行的時候

      ```
        [replaySubject subscribeNext:^(id x) {
                   NSLog(@"Subscriber 3 get a next value: %@ from replay 
                   subject", x);
                }];
      ```
      

      replaySubject會首先發(fā)送之前保存的值也就是send package 1,從而有了

      2017-07-03 18:16:02.923 TestObjectProduct[90499:11197356] Subscriber 3 get a next value: send package 1 from replay subject
      
    3. 然后subject又多了一個訂閱者,保存起來;

    4. 到這行的時候

    ```
    [replaySubject subscribeNext:^(id x) {
                NSLog(@"Subscriber 4 get a next value: %@ from replay subject", x);
            }];
    ```
    此時的`replaySubject`有一個值`send package 1`,所以有了
    
    ```
    2017-07-03 18:16:02.923 TestObjectProduct[90499:11197356] Subscriber 4 get a next value: send package 1 from replay subject
    ```
  1. 2s后subject被訂閱,此時subject的訂閱者有4個從而
```
2017-07-03 18:16:03.911 TestObjectProduct[90499:11197356] Subscriber 1 get a next value: send package 2 from subject
2017-07-03 18:16:03.911 TestObjectProduct[90499:11197356] Subscriber 2 get a next value: send package 2 from subject
2017-07-03 18:16:03.912 TestObjectProduct[90499:11197356] Subscriber 3 get a next value: send package 2 from subject
2017-07-03 18:16:03.912 TestObjectProduct[90499:11197356] Subscriber 4 get a next value: send package 2 from subject

```
`replaySubject`也有4個訂閱者

```
2017-07-03 18:16:03.912 TestObjectProduct[90499:11197356] Subscriber 1 get a next value: send package 2 from replay subject
2017-07-03 18:16:03.912 TestObjectProduct[90499:11197356] Subscriber 2 get a next value: send package 2 from replay subject
2017-07-03 18:16:03.912 TestObjectProduct[90499:11197356] Subscriber 3 get a next value: send package 2 from replay subject
2017-07-03 18:16:03.913 TestObjectProduct[90499:11197356] Subscriber 4 get a next value: send package 2 from replay subject

```

總結(jié):

  1. RACSubject這個類會保存所有的訂閱者,一旦被訂閱,就會保存訂閱者,等待有值發(fā)出的時候,就會告訴所有的訂閱者;
  2. RACReplaySubject,是繼承RACSubject的所以和RACSubject一樣會保存訂閱者,然后比父類不同的是它還會保存所有發(fā)送過的值,供有新訂閱者訂閱的時候發(fā)送它漏過的值。

如何將一個冷信號轉(zhuǎn)成熱信號。

熱信號一般在開發(fā)中充當(dāng)?shù)慕巧缦聢D所示:

所謂的熱信號就是使用RACSubject對象訂閱源信號,而其他的訂閱者訂閱RACSubject

按照上圖的理解就有下面的例子

- (void)testSubjectMul {
    RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        NSLog(@"源信號被訂閱了");
        [subscriber sendNext:@"假設(shè)這是網(wǎng)絡(luò)"];
        [subscriber sendCompleted];
        return nil;
    }];
    
    RACSubject *subject = [RACSubject subject];
    
    [subject subscribeNext:^(id x) {
        NSLog(@"訂閱者1訂閱了");
    }];
    
    [subject subscribeNext:^(id x) {
        NSLog(@"訂閱者2訂閱了");
    }];
    
    [subject subscribeNext:^(id x) {
        NSLog(@"訂閱者3訂閱了");
    }];
    
    [signal subscribe:subject];
    
}

輸出

2017-07-04 22:01:14.443 TestObjectProduct[25044:12106160] 源信號被訂閱了
2017-07-04 22:01:14.443 TestObjectProduct[25044:12106160] 訂閱者1訂閱了
2017-07-04 22:01:14.445 TestObjectProduct[25044:12106160] 訂閱者2訂閱了
2017-07-04 22:01:14.445 TestObjectProduct[25044:12106160] 訂閱者3訂閱了

可以看出源信號只被訂閱了一次

  1. 首先創(chuàng)建源信號;
  2. 再創(chuàng)建一個RACSubject信號;
  3. 再對RACSubject信號進(jìn)行訂閱
  4. 最后RACSubject信號對源信號進(jìn)行訂閱。

當(dāng)然RACSubject有提供將冷信號變成熱信號的遍歷方法

- (RACMulticastConnection *)publish;
- (RACMulticastConnection *)multicast:(RACSubject *)subject ;
- (RACSignal *)replay ;
- (RACSignal *)replayLast ; 
- (RACSignal *)replayLazily

我們針對上面的demo分別使用一下

- (RACMulticastConnection *)publish

- (RACMulticastConnection *)publish {
    RACSubject *subject = [[RACSubject subject] setNameWithFormat:@"[%@] -publish", self.name];
    RACMulticastConnection *connection = [self multicast:subject];
    return connection;
}

這個方法沒有主動connect,一般和- (RACSignal *)autoconnect搭配使用,每當(dāng)autoconnect這個信號訂閱的時候觸發(fā)源信號被訂閱;

- (void)testSubjectMul {
    RACSignal *signal = [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        NSLog(@"源信號被訂閱了");
        [subscriber sendNext:@"假設(shè)這是網(wǎng)絡(luò)"];
        [subscriber sendCompleted];
        return nil;
    }] publish] autoconnect];
    
    
    [signal subscribeNext:^(id x) {
        NSLog(@"訂閱者1訂閱了");
    }];
    
    [signal subscribeNext:^(id x) {
        NSLog(@"訂閱者2訂閱了");
    }];
    
    [signal subscribeNext:^(id x) {
        NSLog(@"訂閱者3訂閱了");
    }];
    
   
}

輸出

2017-07-04 22:08:05.356 TestObjectProduct[25121:12113364] 源信號被訂閱了
2017-07-04 22:08:05.356 TestObjectProduct[25121:12113364] 訂閱者1訂閱了

這里為什么只會有訂閱者1執(zhí)行了,是因為autoconnect只允許connect一次,后面執(zhí)行的只是保存了訂閱者,以便下次執(zhí)行使用。

- (RACMulticastConnection *)multicast:(RACSubject *)subject

- (void)testSubjectMul {
    RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        NSLog(@"源信號被訂閱了");
        [subscriber sendNext:@"假設(shè)這是網(wǎng)絡(luò)"];
        [subscriber sendCompleted];
        return nil;
    }];
    
    RACSubject *subject = [RACSubject subject];
    
    RACMulticastConnection *connect  =   [signal multicast:subject];
    
    [subject subscribeNext:^(id x) {
        NSLog(@"訂閱者1訂閱了");
    }];
    
    [subject subscribeNext:^(id x) {
        NSLog(@"訂閱者2訂閱了");
    }];
    
    [subject subscribeNext:^(id x) {
        NSLog(@"訂閱者3訂閱了");
    }];
    
    [connect connect];
    
   
}

輸出

017-07-04 22:12:26.846 TestObjectProduct[25180:12117807] 源信號被訂閱了
2017-07-04 22:12:26.846 TestObjectProduct[25180:12117807] 訂閱者1訂閱了
2017-07-04 22:12:26.846 TestObjectProduct[25180:12117807] 訂閱者2訂閱了
2017-07-04 22:12:26.846 TestObjectProduct[25180:12117807] 訂閱者3訂閱了

- (RACSignal *)replay

- (void)testSubjectMul {
    RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        NSLog(@"源信號被訂閱了");
        [subscriber sendNext:@"假設(shè)這是網(wǎng)絡(luò)"];
        [subscriber sendCompleted];
        return nil;
    }] replay];
    
   
    [signal subscribeNext:^(id x) {
        NSLog(@"訂閱者1訂閱了");
    }];
    
    [signal subscribeNext:^(id x) {
        NSLog(@"訂閱者2訂閱了");
    }];
    
    [signal subscribeNext:^(id x) {
        NSLog(@"訂閱者3訂閱了");
    }];
    
   
}

輸出

2017-07-04 22:14:22.805 TestObjectProduct[25224:12120354] 源信號被訂閱了
2017-07-04 22:14:22.805 TestObjectProduct[25224:12120354] 訂閱者1訂閱了
2017-07-04 22:14:22.806 TestObjectProduct[25224:12120354] 訂閱者2訂閱了
2017-07-04 22:14:22.806 TestObjectProduct[25224:12120354] 訂閱者3訂閱了

這個一調(diào)用replay的時候就對源信號訂閱了,只不過當(dāng)時沒有訂閱者,由于內(nèi)部使用的是RACReplaySubject對象,此時會保存發(fā)送的值,等到訂閱者訂閱的時候就會發(fā)送保存的值了

比如稍微改一下

- (void)testSubjectMul {
    RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        NSLog(@"源信號被訂閱了");
        [subscriber sendNext:@"假設(shè)這是網(wǎng)絡(luò)"];
        [subscriber sendNext:@"假設(shè)這是網(wǎng)絡(luò)"];
        [subscriber sendCompleted];
        return nil;
    }] replay];
    
   
    [signal subscribeNext:^(id x) {
        NSLog(@"訂閱者1訂閱了");
    }];
    
    [signal subscribeNext:^(id x) {
        NSLog(@"訂閱者2訂閱了");
    }];
    
    [signal subscribeNext:^(id x) {
        NSLog(@"訂閱者3訂閱了");
    }];
    
   
}

就會輸出

2017-07-04 22:17:06.612 TestObjectProduct[25277:12124611] 源信號被訂閱了
2017-07-04 22:17:06.613 TestObjectProduct[25277:12124611] 訂閱者1訂閱了
2017-07-04 22:17:06.613 TestObjectProduct[25277:12124611] 訂閱者1訂閱了
2017-07-04 22:17:06.613 TestObjectProduct[25277:12124611] 訂閱者2訂閱了
2017-07-04 22:17:06.613 TestObjectProduct[25277:12124611] 訂閱者2訂閱了
2017-07-04 22:17:06.614 TestObjectProduct[25277:12124611] 訂閱者3訂閱了
2017-07-04 22:17:06.614 TestObjectProduct[25277:12124611] 訂閱者3訂閱了

- (RACSignal *)replayLast

- (void)testSubjectMul {
    RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        NSLog(@"源信號被訂閱了");
        [subscriber sendNext:@"假設(shè)這是網(wǎng)絡(luò)"];
        [subscriber sendNext:@"假設(shè)這是另一個網(wǎng)絡(luò)"];
        [subscriber sendCompleted];
        return nil;
    }] replayLast];
    
   
    [signal subscribeNext:^(id x) {
        NSLog(@"訂閱者1訂閱了--%@",x);
    }];
    
    [signal subscribeNext:^(id x) {
        NSLog(@"訂閱者2訂閱了--%@",x);
    }];
    
    [signal subscribeNext:^(id x) {
        NSLog(@"訂閱者3訂閱了--%@",x);
    }];
    
   
}

輸出

2017-07-04 22:19:52.137 TestObjectProduct[25395:12129467] 源信號被訂閱了
2017-07-04 22:19:52.138 TestObjectProduct[25395:12129467] 訂閱者1訂閱了--假設(shè)這是另一個網(wǎng)絡(luò)
2017-07-04 22:19:52.138 TestObjectProduct[25395:12129467] 訂閱者2訂閱了--假設(shè)這是另一個網(wǎng)絡(luò)
2017-07-04 22:19:52.138 TestObjectProduct[25395:12129467] 訂閱者3訂閱了--假設(shè)這是另一個網(wǎng)絡(luò)

這個和replay類似,唯一的不同就是replay保存所以發(fā)送過的值,而它保存的是最新的發(fā)送的值

- (RACSignal *)replayLazily

這個要和replay對比看,replay方法是即使沒有訂閱者,源信號也會被訂閱,而replayLazily只有當(dāng)返回的信號被訂閱的時候源信號才會被訂閱,先看replay

- (void)testSubjectMul {
    RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        NSLog(@"源信號被訂閱了");
        [subscriber sendNext:@"假設(shè)這是網(wǎng)絡(luò)"];
        [subscriber sendNext:@"假設(shè)這是另一個網(wǎng)絡(luò)"];
        [subscriber sendCompleted];
        return nil;
    }] replay]; 

輸出

2017-07-04 22:24:02.298 TestObjectProduct[25558:12136590] 源信號被訂閱了

再看replayLazily,先看她沒有被訂閱

- (void)testSubjectMul {
    RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        NSLog(@"源信號被訂閱了");
        [subscriber sendNext:@"假設(shè)這是網(wǎng)絡(luò)"];
        [subscriber sendNext:@"假設(shè)這是另一個網(wǎng)絡(luò)"];
        [subscriber sendCompleted];
        return nil;
    }] replayLazily];    
   
}

輸出

再看被訂閱了

- (void)testSubjectMul {
    RACSignal *signal = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        NSLog(@"源信號被訂閱了");
        [subscriber sendNext:@"假設(shè)這是網(wǎng)絡(luò)"];
        [subscriber sendNext:@"假設(shè)這是另一個網(wǎng)絡(luò)"];
        [subscriber sendCompleted];
        return nil;
    }] replayLazily];    
   [signal subscribeNext:^(id x) {
        NSLog(@"訂閱者1訂閱了--%@",x);
    }];
}

輸出

2017-07-04 22:26:56.527 TestObjectProduct[25601:12139422] 源信號被訂閱了
2017-07-04 22:26:56.528 TestObjectProduct[25601:12139422] 訂閱者1訂閱了--假設(shè)這是網(wǎng)絡(luò)
2017-07-04 22:26:56.528 TestObjectProduct[25601:12139422] 訂閱者1訂閱了--假設(shè)這是另一個網(wǎng)絡(luò)

說道這里我們可以修改一下開始那個網(wǎng)絡(luò)請求了

 self.sessionManager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:@"http://api.xxxx.com"]];

    self.sessionManager.requestSerializer = [AFJSONRequestSerializer serializer];
    self.sessionManager.responseSerializer = [AFJSONResponseSerializer serializer];

    @weakify(self)
    RACSignal *fetchData = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        @strongify(self)
        NSURLSessionDataTask *task = [self.sessionManager GET:@"fetchData" parameters:@{@"someParameter": @"someValue"} success:^(NSURLSessionDataTask *task, id responseObject) {
            [subscriber sendNext:responseObject];
            [subscriber sendCompleted];
        } failure:^(NSURLSessionDataTask *task, NSError *error) {
            [subscriber sendError:error];
        }];
        return [RACDisposable disposableWithBlock:^{
            if (task.state != NSURLSessionTaskStateCompleted) {
                [task cancel];
            }
        }];
    }] replayLazily];//只要加一個這個就可以了

    RACSignal *title = [fetchData flattenMap:^RACSignal *(NSDictionary *value) {
        if ([value[@"title"] isKindOfClass:[NSString class]]) {
            return [RACSignal return:value[@"title"]];
        } else {
            return [RACSignal error:[NSError errorWithDomain:@"some error" code:400 userInfo:@{@"originData": value}]];
        }
    }];

    RACSignal *desc = [fetchData flattenMap:^RACSignal *(NSDictionary *value) {
        if ([value[@"desc"] isKindOfClass:[NSString class]]) {
            return [RACSignal return:value[@"desc"]];
        } else {
            return [RACSignal error:[NSError errorWithDomain:@"some error" code:400 userInfo:@{@"originData": value}]];
        }
    }];

    RACSignal *renderedDesc = [desc flattenMap:^RACStream *(NSString *value) {
        NSError *error = nil;
        RenderManager *renderManager = [[RenderManager alloc] init];
        NSAttributedString *rendered = [renderManager renderText:value error:&error];
        if (error) {
            return [RACSignal error:error];
        } else {
            return [RACSignal return:rendered];
        }
    }];

    RAC(self.someLablel, text) = [[title catchTo:[RACSignal return:@"Error"]]  startWith:@"Loading..."];
    RAC(self.originTextView, text) = [[desc catchTo:[RACSignal return:@"Error"]] startWith:@"Loading..."];
    RAC(self.renderedTextView, attributedText) = [[renderedDesc catchTo:[RACSignal return:[[NSAttributedString alloc] initWithString:@"Error"]]] startWith:[[NSAttributedString alloc] initWithString:@"Loading..."]];


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容