? ? ? ?RxSwift
(或者說 RxCocoa
)除了對系統(tǒng)原生的 UI
控件提供了 rx
擴展外,對 URLSession
也進(jìn)行了擴展,從而讓我們可以很方便地發(fā)送 HTTP
請求。
一、請求網(wǎng)絡(luò)數(shù)據(jù)
1,通過 rx.response 請求數(shù)據(jù)
(1)下面代碼我們通過豆瓣提供的音樂頻道列表接口獲取數(shù)據(jù),并將返回結(jié)果輸出到控制臺中。
//創(chuàng)建URL對象
let urlString = "https://www.douban.com/j/app/radio/channels"
let url = URL(string:urlString)
//創(chuàng)建請求對象
let request = URLRequest(url: url!)
//創(chuàng)建并發(fā)起請求
URLSession.shared.rx.response(request: request).subscribe(onNext: {
(response, data) in
//數(shù)據(jù)處理
let str = String(data: data, encoding: String.Encoding.utf8)
print("返回的數(shù)據(jù)是:", str ?? "")
}).disposed(by: disposeBag)
(2)從上面樣例可以發(fā)現(xiàn),不管請求成功與否都會進(jìn)入到 onNext
這個回調(diào)中。如果我們需要根據(jù)響應(yīng)狀態(tài)進(jìn)行一些相應(yīng)操作,比如:
- 狀態(tài)碼在 200 ~ 300 則正常顯示數(shù)據(jù)。
- 如果是異常狀態(tài)碼(比如:404)則彈出告警提示框。
這個借助 response
參數(shù)進(jìn)行判斷即可。我們把 url
改成一個錯誤的地址,運行結(jié)果如下:
//創(chuàng)建URL對象
let urlString = "https://www.douban.com/xxxxxxxxxx/app/radio/channels"
let url = URL(string:urlString)
//創(chuàng)建請求對象
let request = URLRequest(url: url!)
//創(chuàng)建并發(fā)起請求
URLSession.shared.rx.response(request: request).subscribe(onNext: {
(response, data) in
//判斷響應(yīng)結(jié)果狀態(tài)碼
if 200 ..< 300 ~= response.statusCode {
let str = String(data: data, encoding: String.Encoding.utf8)
print("請求成功!返回的數(shù)據(jù)是:", str ?? "")
}else{
print("請求失??!")
}
}).disposed(by: disposeBag)
2,通過 rx.data 請求數(shù)據(jù)
rx.data
與rx.response
的區(qū)別:
- 如果不需要獲取底層的
response
,只需知道請求是否成功,以及成功時返回的結(jié)果,那么建議使用rx.data
。- 因為
rx.data
會自動對響應(yīng)狀態(tài)碼進(jìn)行判斷,只有成功的響應(yīng)(狀態(tài)碼為 200~300)才會進(jìn)入到onNext
這個回調(diào),否則進(jìn)入onError
這個回調(diào)。
(1)如果不需要考慮請求失敗的情況,只對成功返回的結(jié)果做處理可以在 onNext
回調(diào)中進(jìn)行相關(guān)操作。
//創(chuàng)建URL對象
let urlString = "https://www.douban.com/j/app/radio/channels"
let url = URL(string:urlString)
//創(chuàng)建請求對象
let request = URLRequest(url: url!)
//創(chuàng)建并發(fā)起請求
URLSession.shared.rx.data(request: request).subscribe(onNext: {
data in
let str = String(data: data, encoding: String.Encoding.utf8)
print("請求成功!返回的數(shù)據(jù)是:", str ?? "")
}).disposed(by: disposeBag)
(2)如果還要處理失敗的情況,可以在 onError
回調(diào)中操作。
//創(chuàng)建URL對象
let urlString = "https://www.douban.com/xxxxxx/app/radio/channels"
let url = URL(string:urlString)
//創(chuàng)建請求對象
let request = URLRequest(url: url!)
//創(chuàng)建并發(fā)起請求
URLSession.shared.rx.data(request: request).subscribe(onNext: {
data in
let str = String(data: data, encoding: String.Encoding.utf8)
print("請求成功!返回的數(shù)據(jù)是:", str ?? "")
}, onError: { error in
print("請求失??!錯誤原因:", error)
}).disposed(by: disposeBag)
二、手動發(fā)起請求、取消請求
? ? ? ? 在很多情況下,網(wǎng)絡(luò)請求并不是由程序自動發(fā)起的??赡苄枰覀凕c擊個按鈕,或者切換個標(biāo)簽時才去請求數(shù)據(jù)。除了手動發(fā)起請求外,同樣的可能還需要手動取消上一次的網(wǎng)絡(luò)請求(如果未完成)。下面通過樣例演示這個如何實現(xiàn)。
1,效果圖
(1)每次點擊“發(fā)起請求”按鈕則去請求一次數(shù)據(jù)。
(2)如果請求沒返回時,點擊“取消請求”則可將其取消(取消后即使返回數(shù)據(jù)也不處理了)。
2,樣例代碼
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
//“發(fā)起請求”按鈕
@IBOutlet weak var startBtn: UIButton!
//“取消請求”按鈕
@IBOutlet weak var cancelBtn: UIButton!
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
//創(chuàng)建URL對象
let urlString = "https://www.douban.com/j/app/radio/channels"
let url = URL(string:urlString)
//創(chuàng)建請求對象
let request = URLRequest(url: url!)
//發(fā)起請求按鈕點擊
startBtn.rx.tap.asObservable()
.flatMap {
URLSession.shared.rx.data(request: request)
.takeUntil(self.cancelBtn.rx.tap) //如果“取消按鈕”點擊則停止請求
}
.subscribe(onNext: {
data in
let str = String(data: data, encoding: String.Encoding.utf8)
print("請求成功!返回的數(shù)據(jù)是:", str ?? "")
}, onError: { error in
print("請求失敗!錯誤原因:", error)
}).disposed(by: disposeBag)
}
}