RACSignal的一些常用用法,RACSignal常用用法
NSData + RACSupport.h@interface NSData (RACSupport)// Read the data at the URL using -[NSData initWithContentsOfURL:options:error:].// Sends the data or the error.// 返回一個URL非同步請求的訊號量// scheduler 不可為空+ (RACSignal *)rac_readContentsOfURL:(NSURL *)URL options:(NSDataReadingOptions)options scheduler:(RACScheduler *)scheduler;@end
NSData
嘗試這個例子之前,請在Demo工程的info.plist檔案中加入App Transport Security Settings
索引值,並加入Allow Arbitrary Loads
:YES
索引值對,用來開啟iOS下的非安全連線。
可以這樣用
NSURL* url = [NSURL URLWithString:@"http://www.jianshu.com"];RACSignal* getDataSignal = [NSData rac_readContentsOfURL:url options:NSDataReadingUncached scheduler:[RACScheduler mainThreadScheduler]];[getDataSignal subscribeNext:^(id x) { NSLog(@"%@",x); //這裡的x就是NSData資料}];
map函數
如果我們使用NSData
的rac_readContentsOfURL:url
方法下載的是一張圖片,我們肯定希望這個Signal最後輸出的是UIImage
對象,這裡就要用到非常常用的map
函數。
map
函數就像signal
管道上的中間處理器,從這裡走過的signal
都會經過一段處理後,變成新的signal
繼續傳輸。而這個處理過程則在map
函數中由開發人員決定。
將輸出NSData
的signal
轉換為輸出UIImage
NSURL* url = [NSURL URLWithString:@"http://img1.gtimg.com/gamezone/pics/24159/24159840.jpg"];RACSignal* getDataSignal = [NSData rac_readContentsOfURL:url options:NSDataReadingUncached scheduler:[RACScheduler mainThreadScheduler]]; //map函數進行轉換RACSignal* getImageSignal = [getDataSignal map:^id(id value) { if (value) { return [UIImage imageWithData:value]; } return nil;}]; [getImageSignal subscribeNext:^(id x) { NSLog(@"%@",x);}];
merge方法
接著我們提出一個新需求,同時請求三張不同的圖片,並將它們發送的訊號合并成一條訊號量。這裡就需要用到訊號量的merge
方法,如下
NSURL* url = [NSURL URLWithString:@"http://img1.gtimg.com/gamezone/pics/24159/24159840.jpg"];NSURL* url2 = [NSURL URLWithString:@"http://i3.hoopchina.com.cn/blogfile/201306/29/137247593017986.jpg"];NSURL* url3 = [NSURL URLWithString:@"http://img.youxile.com/pic/1301/25170237170.jpg"];RACSignal* getImageSignal1 = [[NSData rac_readContentsOfURL:url options:NSDataReadingUncached scheduler:[RACScheduler mainThreadScheduler]] map:^id(id value) { if (value) { return [UIImage imageWithData:value]; } return nil;}]; RACSignal* getImageSignal2 = [[NSData rac_readContentsOfURL:url2 options:NSDataReadingUncached scheduler:[RACScheduler mainThreadScheduler]] map:^id(id value) { if (value) { return [UIImage imageWithData:value]; } return nil; }]; RACSignal* getImageSignal3 = [[NSData rac_readContentsOfURL:url3 options:NSDataReadingUncached scheduler:[RACScheduler mainThreadScheduler]] map:^id(id value) { if (value) { return [UIImage imageWithData:value]; } return nil; }]; //合併作業RACSignal* mergeSignal = [RACSignal merge:@[getImageSignal1,getImageSignal2,getImageSignal3]]; [mergeSignal subscribeNext:^(id x) { NSLog(@"%@",x);}];```輸出如下:2015-12-30 10:19:08.776 Fahu[1354:39991] <UIImage: 0x7f9ce2ac3730>, {450, 600}2015-12-30 10:19:08.891 Fahu[1354:39991] <UIImage: 0x7f9ce2b02600>, {500, 687}2015-12-30 10:19:09.098 Fahu[1354:39991] <UIImage: 0x7f9ce29a4500>, {500, 346}
###filter函數網路也會有連不上的時候,三張圖片中如果有哪一張請求失敗,我們並不想讓`signal`發送`nil`值過來,可以使用filter函數對`signal`進行篩選。稍微改造一下上面的`mergeSignal`:
RACSignal* mergeSignal = [[RACSignal merge:@[getImageSignal1,getImageSignal2,getImageSignal3]] filter:^BOOL(id value) {return @(!!value);}];`
注意這裡的filter函數返回的是NSNumber型的BOOL值,YES是通過,NO時拒絕通過。
NSURLConnection
有了RAC
,一些簡單的網路請求都可以不用AF架構了。
NSURLConnection+RACSupport.h
+ (RACSignal *)rac_sendAsynchronousRequest:(NSURLRequest *)request;```舉個例子,還是請求圖片NSURL* url = [NSURL URLWithString:@"http://img1.gtimg.com/gamezone/pics/24159/24159840.jpg"];NSURLRequest* request = [NSURLRequest requestWithURL:url];RACSignal* connectionSignal = [NSURLConnection rac_sendAsynchronousRequest:request];[connectionSignal subscribeNext:^(id x) { NSLog(@"%@",x);}];`輸出 <RACTuple: 0x7f826c071c00> ...省略```注意,這個`signal`發送的訊號量是一個`RACTuple`對象。###RACTuple`RACTuple`(元組)類,是`RAC`中專門用來返回多個傳回值的類,這個設計很像swift中的元組。上面例子中的`RACTuple`有兩個傳回值,`x[0]`是http response的頭部資訊,`x[1]`是請求返回的資料,是一個`NSData`對象。元組類對象的讀取方法和數組相同。