日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

RxSwift之深入解析URLSession的数据请求和数据处理

發(fā)布時(shí)間:2024/5/21 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 RxSwift之深入解析URLSession的数据请求和数据处理 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù)

① 通過(guò) rx.response 請(qǐng)求數(shù)據(jù)

  • 如下所示,通過(guò)豆瓣提供的音樂(lè)頻道列表接口獲取數(shù)據(jù),并將返回結(jié)果輸出到控制臺(tái)中:
"https://www.douban.com/j/app/radio/channels" -i -v Success (2134ms): Status 200 返回的數(shù)據(jù)是: {"channels":[{"name_en":"Personal Radio","seq_id":0,"abbr_en":"My","name":"私人兆赫","channel_id":0},{"name":"華語(yǔ)","seq_id":0,"abbr_en":"","channel_id":"1","name_en":""},{"name":"歐美","seq_id":1,"abbr_en":"","channel_id":"2","name_en":""},{"name":"七零","seq_id":2,"abbr_en":"","channel_id":"3","name_en":""},{"name":"八零","seq_id":3,"abbr_en":"","channel_id":"4","name_en":""},{"name":"九零","seq_id":4,"abbr_en":"","channel_id":"5","name_en":""},{"name":"粵語(yǔ)","seq_id":5,"abbr_en":"","channel_id":"6","name_en":""},{"name":"搖滾","seq_id":6,"abbr_en":"","channel_id":"7","name_en":""},{"name":"民謠","seq_id":7,"abbr_en":"","channel_id":"8","name_en":""},{"name":"輕音樂(lè)","seq_id":8,"abbr_en":"","channel_id":"9","name_en":""},{"name":"原聲","seq_id":9,"abbr_en":"","channel_id":"10","name_en":""},{"name":"Fly by midnight ","seq_id":10,"abbr_en":"","channel_id":"267","name_en":""},{"name":"獨(dú)立","seq_id":11,"abbr_en":"","channel_id":"268","name_en":""},{"name":"爵士","seq_id":12,"abbr_en":"","channel_id":"13","name_en":""},{"name":"電子","seq_id":13,"abbr_en":"","channel_id":"14","name_en":""},{"name":"說(shuō)唱","seq_id":14,"abbr_en":"","channel_id":"15","name_en":""},{"name":"R&B ","seq_id":15,"abbr_en":"","channel_id":"16","name_en":""},{"name":"日語(yǔ)","seq_id":16,"abbr_en":"","channel_id":"17","name_en":""},{"name":"韓語(yǔ)","seq_id":17,"abbr_en":"","channel_id":"18","name_en":""},{"name":"我的巴比倫戀人","seq_id":18,"abbr_en":"","channel_id":"259","name_en":""},{"name":"女聲","seq_id":19,"abbr_en":"","channel_id":"20","name_en":""},{"name":"法語(yǔ)","seq_id":20,"abbr_en":"","channel_id":"22","name_en":""},{"name":"戶外","seq_id":21,"abbr_en":"","channel_id":"151","name_en":""},{"name":"休息","seq_id":22,"abbr_en":"","channel_id":"152","name_en":""},{"name":"工作學(xué)習(xí)","seq_id":23,"abbr_en":"","channel_id":"153","name_en":""},{"name":"亢奮","seq_id":24,"abbr_en":"","channel_id":"154","name_en":""},{"name":"古典","seq_id":25,"abbr_en":"","channel_id":"27","name_en":""},{"name":"動(dòng)漫","seq_id":26,"abbr_en":"","channel_id":"28","name_en":""},{"name":"咖啡館","seq_id":27,"abbr_en":"","channel_id":"32","name_en":""},{"name":"舒緩","seq_id":28,"abbr_en":"","channel_id":"155","name_en":""},{"name":"18歲青春的召喚","seq_id":29,"abbr_en":"","channel_id":"262","name_en":""},{"name":"紅歌","seq_id":30,"abbr_en":"","channel_id":"41","name_en":""},{"name":"圣誕","seq_id":31,"abbr_en":"","channel_id":"170","name_en":""},{"name":"運(yùn)動(dòng)","seq_id":32,"abbr_en":"","channel_id":"257","name_en":""},{"name":"英語(yǔ)","seq_id":33,"abbr_en":"","channel_id":"264","name_en":""},{"name":"豆瓣好歌曲","seq_id":34,"abbr_en":"","channel_id":"179","name_en":""},{"name":"Future Pop","seq_id":35,"abbr_en":"","channel_id":"266","name_en":""},{"name":"金屬","seq_id":36,"abbr_en":"","channel_id":"187","name_en":""},{"name":"布魯斯","seq_id":37,"abbr_en":"","channel_id":"188","name_en":""},{"name":"新歌","seq_id":38,"abbr_en":"","channel_id":"61","name_en":""},{"name":"世界杯","seq_id":39,"abbr_en":"","channel_id":"201","name_en":""},{"name":"朋克","seq_id":40,"abbr_en":"","channel_id":"76","name_en":""},{"name":"Easy ","seq_id":41,"abbr_en":"","channel_id":"77","name_en":""},{"name":"91.1 ","seq_id":42,"abbr_en":"","channel_id":"78","name_en":""},{"name":"鄉(xiāng)村","seq_id":43,"abbr_en":"","channel_id":"269","name_en":""},{"name":"“磚”屬音樂(lè)","seq_id":44,"abbr_en":"","channel_id":"145","name_en":""},{"name":"Pop","seq_id":45,"abbr_en":"","channel_id":"194","name_en":""},{"name":"拉丁","seq_id":46,"abbr_en":"","channel_id":"189","name_en":""}]}
  • 請(qǐng)求示例如下:
// 創(chuàng)建URL對(duì)象 let urlString = "https://www.douban.com/j/app/radio/channels" let url = URL(string:urlString) // 創(chuàng)建請(qǐng)求對(duì)象 let request = URLRequest(url: url!)// 創(chuàng)建并發(fā)起請(qǐng)求 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)
  • 從以上示例,可以看到,不管請(qǐng)求成功與否都會(huì)進(jìn)入到 onNext 這個(gè)回調(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 改成一個(gè)錯(cuò)誤的地址:
// 創(chuàng)建URL對(duì)象 let urlString = "https://www.douban.com/xxxxxxxxxx/app/radio/channels" let url = URL(string:urlString) // 創(chuàng)建請(qǐng)求對(duì)象 let request = URLRequest(url: url!)// 創(chuàng)建并發(fā)起請(qǐng)求 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("請(qǐng)求成功!返回的數(shù)據(jù)是:", str ?? "")}else{print("請(qǐng)求失敗!")} }).disposed(by: disposeBag)
  • 運(yùn)行結(jié)果如下:
curl -X GET "https://www.douban.com/xxxxxxxxxx/app/radio/channels" -i -v Failure (1448ms): Status 404 請(qǐng)求失敗!

② 通過(guò) rx.data 請(qǐng)求數(shù)據(jù)

  • rx.data 與 rx.response 的區(qū)別:
    • 如果不需要獲取底層的 response,只需知道請(qǐng)求是否成功,以及成功時(shí)返回的結(jié)果,那么建議使用 rx.data。
    • 因?yàn)?rx.data 會(huì)自動(dòng)對(duì)響應(yīng)狀態(tài)碼進(jìn)行判斷,只有成功的響應(yīng)(狀態(tài)碼為 200~300)才會(huì)進(jìn)入到 onNext 這個(gè)回調(diào),否則進(jìn)入 onError 這個(gè)回調(diào)。
  • 如果不需要考慮請(qǐng)求失敗的情況,只對(duì)成功返回的結(jié)果做處理可以在 onNext 回調(diào)中進(jìn)行相關(guān)操作:
// 創(chuàng)建URL對(duì)象 let urlString = "https://www.douban.com/j/app/radio/channels" let url = URL(string:urlString) // 創(chuàng)建請(qǐng)求對(duì)象 let request = URLRequest(url: url!)// 創(chuàng)建并發(fā)起請(qǐng)求 URLSession.shared.rx.data(request: request).subscribe(onNext: {data inlet str = String(data: data, encoding: String.Encoding.utf8)print("請(qǐng)求成功!返回的數(shù)據(jù)是:", str ?? "") }).disposed(by: disposeBag)
  • 運(yùn)行結(jié)果:
"https://www.douban.com/j/app/radio/channels" -i -v Success (1449ms): Status 200 請(qǐng)求成功!返回的數(shù)據(jù)是: {"channels":[{"name_en":"Personal Radio","seq_id":0,"abbr_en":"My","name":"私人兆赫","channel_id":0},{"name":"華語(yǔ)","seq_id":0,"abbr_en":"","channel_id":"1","name_en":""},{"name":"歐美","seq_id":1,"abbr_en":"","channel_id":"2","name_en":""},{"name":"七零","seq_id":2,"abbr_en":"","channel_id":"3","name_en":""},{"name":"八零","seq_id":3,"abbr_en":"","channel_id":"4","name_en":""},{"name":"九零","seq_id":4,"abbr_en":"","channel_id":"5","name_en":""},{"name":"粵語(yǔ)","seq_id":5,"abbr_en":"","channel_id":"6","name_en":""},{"name":"搖滾","seq_id":6,"abbr_en":"","channel_id":"7","name_en":""},{"name":"民謠","seq_id":7,"abbr_en":"","channel_id":"8","name_en":""},{"name":"輕音樂(lè)","seq_id":8,"abbr_en":"","channel_id":"9","name_en":""},{"name":"原聲","seq_id":9,"abbr_en":"","channel_id":"10","name_en":""},{"name":"Fly by midnight ","seq_id":10,"abbr_en":"","channel_id":"267","name_en":""},{"name":"獨(dú)立","seq_id":11,"abbr_en":"","channel_id":"268","name_en":""},{"name":"爵士","seq_id":12,"abbr_en":"","channel_id":"13","name_en":""},{"name":"電子","seq_id":13,"abbr_en":"","channel_id":"14","name_en":""},{"name":"說(shuō)唱","seq_id":14,"abbr_en":"","channel_id":"15","name_en":""},{"name":"R&B ","seq_id":15,"abbr_en":"","channel_id":"16","name_en":""},{"name":"日語(yǔ)","seq_id":16,"abbr_en":"","channel_id":"17","name_en":""},{"name":"韓語(yǔ)","seq_id":17,"abbr_en":"","channel_id":"18","name_en":""},{"name":"我的巴比倫戀人","seq_id":18,"abbr_en":"","channel_id":"259","name_en":""},{"name":"女聲","seq_id":19,"abbr_en":"","channel_id":"20","name_en":""},{"name":"法語(yǔ)","seq_id":20,"abbr_en":"","channel_id":"22","name_en":""},{"name":"戶外","seq_id":21,"abbr_en":"","channel_id":"151","name_en":""},{"name":"休息","seq_id":22,"abbr_en":"","channel_id":"152","name_en":""},{"name":"工作學(xué)習(xí)","seq_id":23,"abbr_en":"","channel_id":"153","name_en":""},{"name":"亢奮","seq_id":24,"abbr_en":"","channel_id":"154","name_en":""},{"name":"古典","seq_id":25,"abbr_en":"","channel_id":"27","name_en":""},{"name":"動(dòng)漫","seq_id":26,"abbr_en":"","channel_id":"28","name_en":""},{"name":"咖啡館","seq_id":27,"abbr_en":"","channel_id":"32","name_en":""},{"name":"舒緩","seq_id":28,"abbr_en":"","channel_id":"155","name_en":""},{"name":"18歲青春的召喚","seq_id":29,"abbr_en":"","channel_id":"262","name_en":""},{"name":"紅歌","seq_id":30,"abbr_en":"","channel_id":"41","name_en":""},{"name":"圣誕","seq_id":31,"abbr_en":"","channel_id":"170","name_en":""},{"name":"運(yùn)動(dòng)","seq_id":32,"abbr_en":"","channel_id":"257","name_en":""},{"name":"英語(yǔ)","seq_id":33,"abbr_en":"","channel_id":"264","name_en":""},{"name":"豆瓣好歌曲","seq_id":34,"abbr_en":"","channel_id":"179","name_en":""},{"name":"Future Pop","seq_id":35,"abbr_en":"","channel_id":"266","name_en":""},{"name":"金屬","seq_id":36,"abbr_en":"","channel_id":"187","name_en":""},{"name":"布魯斯","seq_id":37,"abbr_en":"","channel_id":"188","name_en":""},{"name":"新歌","seq_id":38,"abbr_en":"","channel_id":"61","name_en":""},{"name":"世界杯","seq_id":39,"abbr_en":"","channel_id":"201","name_en":""},{"name":"朋克","seq_id":40,"abbr_en":"","channel_id":"76","name_en":""},{"name":"Easy ","seq_id":41,"abbr_en":"","channel_id":"77","name_en":""},{"name":"91.1 ","seq_id":42,"abbr_en":"","channel_id":"78","name_en":""},{"name":"鄉(xiāng)村","seq_id":43,"abbr_en":"","channel_id":"269","name_en":""},{"name":"“磚”屬音樂(lè)","seq_id":44,"abbr_en":"","channel_id":"145","name_en":""},{"name":"Pop","seq_id":45,"abbr_en":"","channel_id":"194","name_en":""},{"name":"拉丁","seq_id":46,"abbr_en":"","channel_id":"189","name_en":""}]}
  • 如果還要處理失敗的情況,可以在 onError 回調(diào)中操作:
// 創(chuàng)建URL對(duì)象 let urlString = "https://www.douban.com/xxxxxx/app/radio/channels" let url = URL(string:urlString) // 創(chuàng)建請(qǐng)求對(duì)象 let request = URLRequest(url: url!)// 創(chuàng)建并發(fā)起請(qǐng)求 URLSession.shared.rx.data(request: request).subscribe(onNext: {data inlet str = String(data: data, encoding: String.Encoding.utf8)print("請(qǐng)求成功!返回的數(shù)據(jù)是:", str ?? "") }, onError: { error inprint("請(qǐng)求失敗!錯(cuò)誤原因:", error) }).disposed(by: disposeBag)
  • 運(yùn)行結(jié)果:
"https://www.douban.com/xxxxxx/app/radio/channels" -i -v Failure (7189ms): Status 404 請(qǐng)求失敗!錯(cuò)誤原因: HTTP request failed with `404`.

二、手動(dòng)發(fā)起請(qǐng)求和取消請(qǐng)求

  • 在很多情況下,網(wǎng)絡(luò)請(qǐng)求并不是由程序自動(dòng)發(fā)起的,可能需要我們點(diǎn)擊個(gè)按鈕,或者切換個(gè)標(biāo)簽時(shí)才去請(qǐng)求數(shù)據(jù)。除了手動(dòng)發(fā)起請(qǐng)求外,同樣的可能還需要手動(dòng)取消上一次的網(wǎng)絡(luò)請(qǐng)求(如果未完成),那么 RxSwift 該如何實(shí)現(xiàn)呢?
  • 如下所示:
    • 每次點(diǎn)擊“發(fā)起請(qǐng)求”按鈕則去請(qǐng)求一次數(shù)據(jù);
    • 如果請(qǐng)求沒(méi)返回時(shí),點(diǎn)擊“取消請(qǐng)求”則可將其取消(取消后即使返回?cái)?shù)據(jù)也不作處理)。
//“發(fā)起請(qǐng)求”按鈕@IBOutlet weak var startBtn: UIButton!//“取消請(qǐng)求”按鈕@IBOutlet weak var cancelBtn: UIButton!let disposeBag = DisposeBag()override func viewDidLoad() {super.viewDidLoad()//創(chuàng)建URL對(duì)象let urlString = "https://www.douban.com/j/app/radio/channels"let url = URL(string:urlString)//創(chuàng)建請(qǐng)求對(duì)象let request = URLRequest(url: url!)//發(fā)起請(qǐng)求按鈕點(diǎn)擊startBtn.rx.tap.asObservable().flatMap {URLSession.shared.rx.data(request: request).takeUntil(self.cancelBtn.rx.tap) //如果“取消按鈕”點(diǎn)擊則停止請(qǐng)求}.subscribe(onNext: {data inlet str = String(data: data, encoding: String.Encoding.utf8)print("請(qǐng)求成功!返回的數(shù)據(jù)是:", str ?? "")}, onError: { error inprint("請(qǐng)求失敗!錯(cuò)誤原因:", error)}).disposed(by: disposeBag)

三、將結(jié)果轉(zhuǎn)為 Json 對(duì)象

  • 如果服務(wù)器返回的數(shù)據(jù)是 json 格式的話,可以使用 iOS 內(nèi)置的 JSONSerialization 將其轉(zhuǎn)成 JSON 對(duì)象,方便使用:
// 創(chuàng)建URL對(duì)象 let urlString = "https://www.douban.com/j/app/radio/channels" let url = URL(string:urlString) // 創(chuàng)建請(qǐng)求對(duì)象 let request = URLRequest(url: url!)// 創(chuàng)建并發(fā)起請(qǐng)求 URLSession.shared.rx.data(request: request).subscribe(onNext: {data inlet json = try? (JSONSerialization.jsonObject(with: data, options: .allowFragments)as! [String: Any])print("--- 請(qǐng)求成功,返回的如下數(shù)據(jù) ---")print(json!) }).disposed(by: disposeBag)
  • 運(yùn)行結(jié)果如下:
"https://www.douban.com/j/app/radio/channels" -i -v Success (3410ms): Status 200 --- 請(qǐng)求成功!返回的如下數(shù)據(jù) --- ["channels": <__NSArrayI 0x7ff0f2f07080>( {"abbr_en" = "";"channel_id" = 9;name = "\U8f7b\U97f3\U4e50";"name_en" = "";"seq_id" = 8; }, {"abbr_en" = "";"channel_id" = 10;name = "\U539f\U58f0";"name_en" = "";"seq_id" = 9; }, {"abbr_en" = "";"channel_id" = 267;name = "Fly by midnight ";"name_en" = "";"seq_id" = 10; }, {"abbr_en" = "";"channel_id" = 268;name = "\U72ec\U7acb";"name_en" = "";"seq_id" = 11; }, {"abbr_en" = "";"channel_id" = 13;name = "\U7235\U58eb";"name_en" = "";"seq_id" = 12; }, {"abbr_en" = "";"channel_id" = 14;name = "\U7535\U5b50";"name_en" = "";"seq_id" = 13; }, {"abbr_en" = "";"channel_id" = 15;name = "\U8bf4\U5531";"name_en" = "";"seq_id" = 14; }, {"abbr_en" = "";"channel_id" = 16;name = "R&B ";"name_en" = "";"seq_id" = 15; }, {"abbr_en" = "";"channel_id" = 17;name = "\U65e5\U8bed";"name_en" = "";"seq_id" = 16; }, {"abbr_en" = "";"channel_id" = 18;name = "\U97e9\U8bed";"name_en" = "";"seq_id" = 17; }, {"abbr_en" = "";"channel_id" = 259;name = "\U6211\U7684\U5df4\U6bd4\U4f26\U604b\U4eba";"name_en" = "";"seq_id" = 18; }, {"abbr_en" = "";"channel_id" = 20;name = "\U5973\U58f0";"name_en" = "";"seq_id" = 19; }, {"abbr_en" = "";"channel_id" = 22;name = "\U6cd5\U8bed";"name_en" = "";"seq_id" = 20; }, {"abbr_en" = "";"channel_id" = 151;name = "\U6237\U5916";"name_en" = "";"seq_id" = 21; }, {"abbr_en" = "";"channel_id" = 152;name = "\U4f11\U606f";"name_en" = "";"seq_id" = 22; }, {"abbr_en" = "";"channel_id" = 28;name = "\U52a8\U6f2b";"name_en" = "";"seq_id" = 26; }, {"abbr_en" = "";"channel_id" = 32;name = "\U5496\U5561\U9986";"name_en" = "";"seq_id" = 27; }, {"abbr_en" = "";"channel_id" = 155;name = "\U8212\U7f13";"name_en" = "";"seq_id" = 28; }, {"abbr_en" = "";"channel_id" = 262;name = "18\U5c81\U9752\U6625\U7684\U53ec\U5524";"name_en" = "";"seq_id" = 29; }, {"abbr_en" = "";"channel_id" = 41;name = "\U7ea2\U6b4c";"name_en" = "";"seq_id" = 30; }, {"abbr_en" = "";"channel_id" = 170;name = "\U5723\U8bde";"name_en" = "";"seq_id" = 31; }, {"abbr_en" = "";"channel_id" = 257;name = "\U8fd0\U52a8";"name_en" = "";"seq_id" = 32; }, {"abbr_en" = "";"channel_id" = 264;name = "\U82f1\U8bed";"name_en" = "";"seq_id" = 33; }, {"abbr_en" = "";"channel_id" = 179;name = "\U8c46\U74e3\U597d\U6b4c\U66f2";"name_en" = "";"seq_id" = 34; } ) ]
  • 也可以在訂閱前就進(jìn)行轉(zhuǎn)換:
// 創(chuàng)建URL對(duì)象 let urlString = "https://www.douban.com/j/app/radio/channels" let url = URL(string:urlString) // 創(chuàng)建請(qǐng)求對(duì)象 let request = URLRequest(url: url!)// 創(chuàng)建并發(fā)起請(qǐng)求 URLSession.shared.rx.data(request: request).map {try JSONSerialization.jsonObject(with: $0, options: .allowFragments)as! [String: Any]}.subscribe(onNext: {data inprint("--- 請(qǐng)求成功!返回的如下數(shù)據(jù) ---")print(data)}).disposed(by: disposeBag)
  • 還有更簡(jiǎn)單的方法,就是直接使用 RxSwift 提供的 rx.json 方法去獲取數(shù)據(jù),它會(huì)直接將結(jié)果轉(zhuǎn)成 Json 對(duì)象:
// 創(chuàng)建URL對(duì)象 let urlString = "https://www.douban.com/j/app/radio/channels" let url = URL(string:urlString) // 創(chuàng)建請(qǐng)求對(duì)象 let request = URLRequest(url: url!)// 創(chuàng)建并發(fā)起請(qǐng)求 URLSession.shared.rx.json(request: request).subscribe(onNext: {data inlet json = data as! [String: Any]print("--- 請(qǐng)求成功!返回的如下數(shù)據(jù) ---")print(json ) }).disposed(by: disposeBag)
  • 將獲取到的豆瓣頻道列表數(shù)據(jù)轉(zhuǎn)換成 Json 對(duì)象,并綁定到表格上顯示:
// 創(chuàng)建表格視圖 self.tableView = UITableView(frame: self.view.frame, style:.plain) // 創(chuàng)建一個(gè)重用的單元格 self.tableView!.register(UITableViewCell.self, forCellReuseIdentifier: "Cell") self.view.addSubview(self.tableView!)// 創(chuàng)建URL對(duì)象 let urlString = "https://www.douban.com/j/app/radio/channels" let url = URL(string:urlString) // 創(chuàng)建請(qǐng)求對(duì)象 let request = URLRequest(url: url!)// 獲取列表數(shù)據(jù) let data = URLSession.shared.rx.json(request: request).map{ result -> [[String: Any]] inif let data = result as? [String: Any],let channels = data["channels"] as? [[String: Any]] {return channels}else{return []} }// 將數(shù)據(jù)綁定到表格 data.bind(to: tableView.rx.items) { (tableView, row, element) inlet cell = tableView.dequeueReusableCell(withIdentifier: "Cell")!cell.textLabel?.text = "\(row)\(element["name"]!)"return cell }.disposed(by: disposeBag)
  • 效果如下:

四、將結(jié)果映射成自定義對(duì)象

① 準(zhǔn)備工作

  • 要實(shí)現(xiàn)數(shù)據(jù)到模型(model)的轉(zhuǎn)換,首先需要引入一個(gè)第三方的數(shù)據(jù)模型轉(zhuǎn)換框架:ObjectMapper。
  • 為了讓 ObjectMapper 能夠更好地與 RxSwift 配合使用,對(duì) Observable 進(jìn)行擴(kuò)展(RxObjectMapper.swift),增加數(shù)據(jù)轉(zhuǎn)模型對(duì)象、以及數(shù)據(jù)轉(zhuǎn)模型對(duì)象數(shù)組這兩個(gè)方法:
import ObjectMapper import RxSwift// 數(shù)據(jù)映射錯(cuò)誤 public enum RxObjectMapperError: Error {case parsingError }// 擴(kuò)展Observable:增加模型映射方法 public extension Observable where Element:Any {// 將Json數(shù)據(jù)轉(zhuǎn)成對(duì)象public func mapObject< T>(type:T.Type) -> Observable<T> where T:Mappable {let mapper = Mapper<T>()return self.map { (element) -> T inguard let parsedElement = mapper.map(JSONObject: element) else {throw RxObjectMapperError.parsingError}return parsedElement}}// 將Json數(shù)據(jù)轉(zhuǎn)成數(shù)組public func mapArray< T>(type:T.Type) -> Observable<[T]> where T:Mappable {let mapper = Mapper<T>()return self.map { (element) -> [T] inguard let parsedArray = mapper.mapArray(JSONObject: element) else {throw RxObjectMapperError.parsingError}return parsedArray}} }

② 使用示例

  • 以豆瓣音樂(lè)頻道數(shù)據(jù)為例,首先定義好相關(guān)模型(需要實(shí)現(xiàn) ObjectMapper 的 Mappable 協(xié)議,并設(shè)置好成員對(duì)象與 Json 屬性的相互映射關(guān)系):
// 豆瓣接口模型 class Douban: Mappable {// 頻道列表var channels: [Channel]?init(){}required init?(map: Map) {}// Mappablefunc mapping(map: Map) {channels <- map["channels"]} }// 頻道模型 class Channel: Mappable {var name: String?var nameEn:String?var channelId: String?var seqId: Int?var abbrEn: String?init(){}required init?(map: Map) {}// Mappablefunc mapping(map: Map) {name <- map["name"]nameEn <- map["name_en"]channelId <- map["channel_id"]seqId <- map["seq_id"]abbrEn <- map["abbr_en"]} }
  • 如下所示,獲取數(shù)據(jù),并轉(zhuǎn)換成對(duì)應(yīng)的模型:
// 創(chuàng)建URL對(duì)象 let urlString = "https://www.douban.com/j/app/radio/channels" let url = URL(string:urlString) // 創(chuàng)建請(qǐng)求對(duì)象 let request = URLRequest(url: url!)// 創(chuàng)建并發(fā)起請(qǐng)求 URLSession.shared.rx.json(request: request).mapObject(type: Douban.self).subscribe(onNext: { (douban: Douban) inif let channels = douban.channels {print("--- 共\(channels.count)個(gè)頻道 ---")for channel in channels {if let name = channel.name, let channelId = channel.channelId {print("\(name) (id:\(channelId))")}}}}).disposed(by: disposeBag)
  • 如下所示,將數(shù)據(jù)換成模型,并綁定到表格上顯示:
// 創(chuàng)建表格視圖 self.tableView = UITableView(frame: self.view.frame, style:.plain) // 創(chuàng)建一個(gè)重用的單元格 self.tableView!.register(UITableViewCell.self, forCellReuseIdentifier: "Cell") self.view.addSubview(self.tableView!)// 創(chuàng)建URL對(duì)象 let urlString = "https://www.douban.com/j/app/radio/channels" let url = URL(string:urlString) // 創(chuàng)建請(qǐng)求對(duì)象 let request = URLRequest(url: url!)// 獲取列表數(shù)據(jù) let data = URLSession.shared.rx.json(request: request).mapObject(type: Douban.self).map{ $0.channels ?? []}// 將數(shù)據(jù)綁定到表格 data.bind(to: tableView.rx.items) { (tableView, row, element) inlet cell = tableView.dequeueReusableCell(withIdentifier: "Cell")!cell.textLabel?.text = "\(row)\(element.name!)"return cell }.disposed(by: disposeBag)

總結(jié)

以上是生活随笔為你收集整理的RxSwift之深入解析URLSession的数据请求和数据处理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。