麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 系統(tǒng) > iOS > 正文

淺談RxSwift 網(wǎng)絡(luò)請(qǐng)求

2019-10-21 18:40:18
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

一、說(shuō)明

入坑RxSwift 有段時(shí)間了,之前在項(xiàng)目中只是小范圍的使用RxSwift,為了更好的使用響應(yīng)式編程,決定在項(xiàng)目中更廣范圍的使用RxSwift,然后研究了一下RxSwift的網(wǎng)絡(luò)請(qǐng)求,現(xiàn)在有關(guān)網(wǎng)絡(luò)請(qǐng)求的案例大多是基于RXSwift(4.0.0)或者更早的庫(kù)來(lái)寫(xiě)的,本篇文章是基于目前最新的版本(4.2.0)版本來(lái)寫(xiě)的,由于RxSwift 版本的更新,里面的使用語(yǔ)法,發(fā)生了變化,在整理的過(guò)程中遇到了一些問(wèn)題,為了讓后來(lái)學(xué)習(xí)的小伙伴,節(jié)約時(shí)間,決定記錄下來(lái)

二、網(wǎng)絡(luò)請(qǐng)求

1.使用RxSwift相關(guān)庫(kù)的版本

  • ObjectMapper (3.2.0)
  • HandyJSON (4.1.1)
  • Moya (11.0.2)
  • RxCocoa (4.2.0)
  • RxSwift (4.2.0)

2.在Swift語(yǔ)言中,我們使用Alamofire 作為網(wǎng)絡(luò)庫(kù),moya 是對(duì)Alamofire 更抽象一層的封裝,RxSwift把Moya封裝后作為網(wǎng)絡(luò)請(qǐng)求的接口,我們?cè)谑褂玫臅r(shí)候只需要實(shí)現(xiàn) TargetType 協(xié)議就好,用一個(gè)例子來(lái)看下怎么使用:

import Foundationimport Moyaenum APIService{  case mainClassList}extension APIService:TargetType{  var baseURL: URL {    return URL(string:"http://cmsadmin.fotoable.net")!  }    var path: String {    switch self {    case .mainClassList:       return "/sandboxColor/category"    }  }    var method: Moya.Method {    switch self {    case .mainClassList:       return .get    }  }    var parameters: [String : Any]? {        switch self {    case .mainClassList:      return nil    }  }    var parameterEncoding: ParameterEncoding {        return URLEncoding.default  }    var sampleData: Data {    return "{}".data(using: String.Encoding.utf8)!  }    var task: Task {    return .requestPlain  }    var headers: [String : String]? {    return nil  }}

首先,我們定義了一個(gè) 枚舉 APIService ,作用主要是在內(nèi)部定義網(wǎng)絡(luò)請(qǐng)求的接口,然后,就是對(duì)協(xié)議 TargetType進(jìn)行擴(kuò)展,我們一一解讀下里面的參數(shù)

  • baseURL:網(wǎng)絡(luò)請(qǐng)求的基本URL
  • path:用于匹配具體網(wǎng)絡(luò)請(qǐng)求接口
  • method:網(wǎng)絡(luò)請(qǐng)求方式,常用就是 get/post 兩種
  • parameters:接口請(qǐng)求時(shí)要帶的參數(shù)
  • parameterEncoding:參數(shù)編碼方式(這里使用URL的默認(rèn)方式)
  • sampleData:這里用于單元測(cè)試
  • task:執(zhí)行網(wǎng)絡(luò)請(qǐng)求的任務(wù)
  • validationType:是否執(zhí)行Alamofire驗(yàn)證,默認(rèn)值為false
  • headers:網(wǎng)絡(luò)請(qǐng)求時(shí)需要的header,如果和后臺(tái)沒(méi)有特殊的驗(yàn)證處理,默認(rèn)傳nil 就可以
  • APIService 作為網(wǎng)絡(luò)請(qǐng)求的統(tǒng)一接口,里面封裝了網(wǎng)絡(luò)請(qǐng)求所需的一些基本數(shù)據(jù)

3.在進(jìn)行網(wǎng)絡(luò)請(qǐng)求之前,需要做一些準(zhǔn)備工作,把網(wǎng)絡(luò)請(qǐng)求回的數(shù)據(jù)通過(guò)JSON 轉(zhuǎn)化成 Model , 這里我們使用了兩種方式進(jìn)行轉(zhuǎn)換(根據(jù)項(xiàng)目的情況,靈活選擇使用),一種通過(guò) ObjectMapper庫(kù)進(jìn)行轉(zhuǎn)換,一種是通過(guò) HandyJSON 庫(kù) 進(jìn)行轉(zhuǎn)換 ,分別通過(guò)對(duì) Response 類 擴(kuò)展 ,以下是對(duì)這兩種方式的封裝

其一:使用 ObjectMapper庫(kù) 把JSON 轉(zhuǎn)換成 Model

import Foundationimport RxSwiftimport Moyaimport ObjectMapper// MARK: - Json -> Modelextension Response {    func mapObjectModel<T: BaseMappable>(_ type: T.Type, context: MapContext? = nil) throws -> T {    guard let object = Mapper<T>(context: context).map(JSONObject: try mapJSON()) else {      throw MoyaError.jsonMapping(self)    }    return object  }    func mapObjectArray<T: BaseMappable>(_ type: T.Type, context: MapContext? = nil) throws -> [T] {    guard let array = try mapJSON() as? [[String : Any]] else {      throw MoyaError.jsonMapping(self)    }    return Mapper<T>(context: context).mapArray(JSONArray: array)  }}// MARK: - Json -> Observable<Model>extension ObservableType where E == Response {  // 將Json解析為Observable<Model>  public func mapObjectModel<T: BaseMappable>(_ type: T.Type) -> Observable<T> {    return flatMap { response -> Observable<T> in      return Observable.just(try response.mapObjectModel(T.self))    }  }  // 將Json解析為Observable<[Model]>  public func mapObjectArray<T: BaseMappable>(_ type: T.Type) -> Observable<[T]> {    return flatMap { response -> Observable<[T]> in      return Observable.just(try response.mapObjectArray(T.self))    }  }}

其二 : 使用 HandyJSON 庫(kù) 把JSON 轉(zhuǎn)化成 Model

import Foundationimport RxSwiftimport Moyaimport HandyJSONextension ObservableType where E == Response {  public func mapHandyJsonModel<T: HandyJSON>(_ type: T.Type) -> Observable<T> {    return flatMap { response -> Observable<T> in      return Observable.just(response.mapHandyJsonModel(T.self))    }  }}extension Response {  func mapHandyJsonModel<T: HandyJSON>(_ type: T.Type) -> T {    let jsonString = String.init(data: data, encoding: .utf8)    if let modelT = JSONDeserializer<T>.deserializeFrom(json: jsonString) {      return modelT    }    return JSONDeserializer<T>.deserializeFrom(json: "{/"msg/":/"請(qǐng)求有誤/"}")!  }}

4.在MainClassViewModel中,使用已經(jīng)封裝好的接口進(jìn)行網(wǎng)絡(luò)請(qǐng)求,代碼如下:

import RxSwiftimport Moyaimport ObjectMapperimport HandyJSONimport RxCocoaclass MainClassViewModel {  private let provider = MoyaProvider<APIService>()  let disposeBag = DisposeBag()  var dataSource = BehaviorRelay<[MainClassModelMapObject_sub]>(value:[])  var networkError = BehaviorRelay(value: Error.self)}//MARK: -- 網(wǎng)絡(luò)extension MainClassViewModel {    //網(wǎng)絡(luò)請(qǐng)求-- ObjectMapper  func getClassListWithMapObject(){    provider.rx.request(.mainClassList).asObservable().mapObjectModel(MainClassModelMapObject.self).subscribe({ [unowned self] (event) in            switch event {      case let .next(classModel):        print("ObjectMapper -- 加載網(wǎng)絡(luò)成功")        self.dataSource.accept(classModel.data)              case let .error( error):        print("error:", error)        self.networkError.accept(error as! Error.Protocol)      case .completed: break      }    }).disposed(by: self.disposeBag)  }      //網(wǎng)絡(luò)請(qǐng)求-- HandyJSON  func getClassListWithMapHandyJson(){    provider.rx.request(.mainClassList).asObservable().mapHandyJsonModel(MainClassModel.self).subscribe({ [unowned self] (event) in            switch event {      case let .next(classModel):                print("HandyJSON -- 加載網(wǎng)絡(luò)成功")              case let .error( error):        print("error:", error)        self.networkError.accept(error as! Error.Protocol)      case .completed: break      }    }).disposed(by: self.disposeBag)  }  }

這里用了兩種方式,分別對(duì) mainClassList API 接口進(jìn)行了網(wǎng)絡(luò)請(qǐng)求,唯一不同的是,在得到到網(wǎng)絡(luò)請(qǐng)求回來(lái)數(shù)據(jù)的時(shí)候,一個(gè)是使用 mapObjectModel 把JSON 轉(zhuǎn)化成 Model ,一個(gè)是使用 mapHandyJsonModel 把 JSON轉(zhuǎn)化成Model ,由于我們使用的是不同的庫(kù),把JSON 轉(zhuǎn)化成 Model,這兩種實(shí)現(xiàn)的方式還是有一些差別,下面是這兩種 Model 的具體實(shí)現(xiàn)方式:

其一、實(shí)現(xiàn)協(xié)議 Mappable

import UIKitimport ObjectMapperclass MainClassModelMapObject: Mappable {    var code:NSInteger?  var data:[MainClassModelMapObject_sub]!    required init?(map: Map) {}    func mapping(map: Map) {    code <- map["code"]    data <- map["data"]  }}class MainClassModelMapObject_sub: Mappable {    var ID:String?  var name:String?  var desc:String?  var imgUrl:String?  var gifUrl:String?  var isUpdate:Bool?  var backgroundGroup:NSInteger?    required init?(map: Map) {}    func mapping(map: Map) {        ID <- map["ID"]    name <- map["name"]    desc <- map["desc"]    imgUrl <- map["imgUrl"]    gifUrl <- map["gifUrl"]    isUpdate <- map["isUpdate"]    backgroundGroup <- map["backgroundGroup"]  }}

其二、實(shí)現(xiàn)協(xié)議 HandyJSON

import UIKitimport HandyJSONstruct MainClassModel: HandyJSON {  var code:NSInteger?  var data:[MainClassModel_sub]!}struct MainClassModel_sub: HandyJSON {    var ID:String?  var name:String?  var desc:String?  var imgUrl:String?  var gifUrl:String?  var isUpdate:Bool?  var backgroundGroup:NSInteger?}

5、以上是使用 RxSwift 進(jìn)行網(wǎng)絡(luò)請(qǐng)求的分析,接下來(lái)看一個(gè)示例如何使用,在MainClassViewModel 中我們使用 dataSource 保存了網(wǎng)絡(luò)請(qǐng)求回來(lái)的數(shù)據(jù),我們要在 ViewController里 用tableview 把這個(gè)數(shù)據(jù)展示出來(lái),需要提前把數(shù)據(jù)源和TableView進(jìn)行綁定,以下是示例代碼:

 //cell   viewModel.dataSource.bind(to: tableView.rx.items) { (tableView, row, element) in      let cell = tableView.dequeueReusableCell(withIdentifier: "MainClassTableViewCell", for: IndexPath(row: row, section: 0)) as! MainClassTableViewCell            cell.setModel(model: element)      // configure cell      return cell      }      .disposed(by: disposeBag)

在需要使用的地方,調(diào)用 方法 getClassListWithMapObject() 或者 getClassListWithMapHandyJson()

三、總結(jié)

這部分的內(nèi)容,適合對(duì)RxSwift 有一定了解的小伙伴學(xué)習(xí), 文章重點(diǎn)是 幫助大家學(xué)習(xí)和了解 RxSwift 網(wǎng)絡(luò)請(qǐng)求的相關(guān)知識(shí),下面是一個(gè)寫(xiě)好的demo

demo

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持VEVB武林網(wǎng)。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到IOS開(kāi)發(fā)頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 精品国产一区二区三区四 | 午夜视频你懂的 | 国产成人精品一区在线播放 | 免费黄色大片在线观看 | 成人国产精品一区二区毛片在线 | 亚洲第五色综合网 | 精品一区二区三区毛片 | 久久久久亚洲a | 毛片在线免费 | 综合在线视频 | 久久久久久久一区 | 91久久91久久精品免观看 | 超碰97在线人人 | 免费高潮在线国 | 久久国产精品二国产精品 | www久久艹| 欧美一级片一区 | 欧美大荫蒂xxx | 一级大片在线观看 | 欧美日韩在线看片 | 免费一级电影 | 久久恋| 性盈盈盈影院 | 免费黄色在线电影 | h视频免费观看 | 国产一级淫 | 热99热 | 牛牛a级毛片在线播放 | 欧美视频一区二区三区 | 国产精品视频免费网站 | 国产亚洲精彩视频 | 亚洲视屏| 日韩黄网站 | 久久精品无码一区二区日韩av | 久久久久久亚洲综合影院红桃 | 午夜精品在线视频 | 成年人网站视频免费 | chinese18 xxxx videos| 成人在线视频免费播放 | 国产乱乱视频 | 国产91丝袜在线播放 |