NSData 嘗試這個例子之前,請在Demo工程的info.plist文件中加入App Transport Security Settings鍵值,並加入Allow Arbitrary Loads:YES鍵值對,用來開啟iOS下的非安全連接。 可以這樣用 map函數 如果我們使用NSData的rac ...
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`對象。元組類對象的讀取方法和數組相同。