Moya 與 RxSwift 使用


如在OC中使用AFNetworking一般,Swift我們用Alamofire來做網絡庫.而Moya在Alamofire的基礎上又封裝了一層:

1.關於moya

moyamoya

官方說moya有以下特性-_-:

  • 編譯時檢查正確的API端點訪問.
  • 使你定義不同端點枚舉值對應相應的用途更加明晰.
  • 提高測試地位從而使單元測試更加容易.

2.開始

1.創建枚舉API

就像這樣:

enum APIManager {
case getNewsLatest//獲取最新消息
case getStartImage// 啟動界面圖像獲取
case getVersion(String)//軟件版本查詢
case getThemes//主題日報列表查看
case getNewsDetail(Int)//獲取新聞詳情
}

 

2.實現TargetType協議

就像這樣:

extension APIManager: TargetType {
 
/// The target's base `URL`.
var baseURL: URL {
 
return URL.init(string: "http://news-at.zhihu.com/api/")!
}
 
/// The path to be appended to `baseURL` to form the full `URL`.
var path: String {
 
switch self {
 
case .getNewsLatest:
return "4/news/latest"
 
case .getStartImage://start-image 后為圖像分辨率,接受任意的 number*number 格式, number 為任意非負整數,返回值均相同。
return "4/start-image/1080*1776"
 
case .getVersion(let version)://URL 最后部分的數字代表所安裝『知乎日報』的版本
return "4/version/ios/" + version
 
case .getThemes:
return "4/themes"
 
case .getNewsDetail(let id):
return "4/news/\(id)"
 
}
 
 
}
 
/// The HTTP method used in the request.
var method: Moya.Method {
 
return .get
}
 
/// The parameters to be incoded in the request.
var parameters: [String: Any]? {
 
return nil
}
 
/// The method used for parameter encoding.
var parameterEncoding: ParameterEncoding {
 
return URLEncoding.default
}
 
/// Provides stub data for use in testing.
var sampleData: Data {
 
return "".data(using: String.Encoding.utf8)!
}
 
/// The type of HTTP task to be performed.
var task: Task {
 
return .request
}
 
/// Whether or not to perform Alamofire validation. Defaults to `false`.
var validate: Bool {
 
return false
}
 
}

 

在這里,可以設置請求的參數,例如url……method……para等.

3.使用

Moya的使用非常簡單,通過TargetType協議定義好每個target之后,就可以直接使用Moya開始發送網絡請求了。就像這樣:

let provider = MoyaProvider<APIManager>()
provider.request(.getNewsLatest) { result in
// do something with result
}

 

3.配合RxSwift

Moya本身已經是一個使用起來非常方便,能夠寫出非常簡潔優雅的代碼的網絡封裝庫,但是讓Moya變得更加強大的原因之一還因為它對於Functional Reactive Programming的擴展,具體說就是對於RxSwiftReactiveCocoa的擴展,通過與這兩個庫的結合,能讓Moya變得更加強大。我選擇RxSwift的原因有兩個,一個是RxSwift的庫相對來說比較輕量級,語法更新相對來說比較少,我之前用過ReactiveCocoa,一些大版本的更新需求重寫很多代碼,第二個更重要的原因是因為RxSwift背后有整個ReactiveX的支持,里面包括JavaJS.NetSwiftScala,它們內部都用了ReactiveX的邏輯思想,這意味着你一旦學會了其中的一個,以后可以很快的上手ReactiveX中的其他語言。

Moya提供了非常方面的RxSwift擴展:

let provider = RxMoyaProvider<APIManager>()
provider.request(.getNewsLatest)
.filterSuccessfulStatusCodes()
.mapJSON()
.subscribe(onNext: { (json) in
//do something with posts
print(json)
})
.addDisposableTo(disposeBag)

 

解釋一下:

  • RxMoyaProviderMoyaProvider的子類,是對RxSwift的擴展

  • filterSuccessfulStatusCodes()MoyaRxSwift提供的擴展方法,顧名思義,可以得到成功地網絡請求,忽略其他的

  • mapJSON()也是Moya RxSwift的擴展方法,可以把返回的數據解析成 JSON 格式

  • subscribe 是一個RxSwift的方法,對經過一層一層處理的 Observable 訂閱一個 onNext 的 observer,一旦得到 JSON 格式的數據,就會經行相應的處理

  • addDisposableTo(disposeBag) 是 RxSwift 的一個自動內存處理機制,跟ARC有點類似,會自動清理不需要的對象。

4.配合HandyJSON

在實際應用過程中網絡請求往往緊密連接着數據層(Model),具體地說,在我們的這個例子中,一般我們需要建立一個類用來統一管理數據,然后把得到的 JSON 數據映射到數據層(Model)。

struct MenuModel: HandyJSON {
var others: [ThemeModel]?
 
}
 
struct ThemeModel: HandyJSON {
 
var color: String?
var thumbnail: String?
var id: Int?
var description: String?
var name: String?
}

 

然后創建ViewModel類,創建具體請求方法:

class MenuViewModel {
 
private let provider = RxMoyaProvider<APIManager>()
var dispose = DisposeBag()
 
func getThemes(completed: @escaping (_ menuModel: MenuModel) -> ()){
 
provider
.request(.getThemes)
.mapModel(MenuModel.self)
.subscribe(onNext: { (model) in
 
completed(model)
}, onError: { (error) in
 
}, onCompleted: nil, onDisposed: nil).addDisposableTo(dispose)
 
}
 
}

 

這里解釋一下:
我這里是將請求的數據通過閉包傳了出去,當然也可以不那么做.個人喜好問題..

這里是為 RxSwift 中的 ObservableType和 Response寫一個簡單的擴展方法 mapModel,利用我們寫好的Model 類,一步就把JSON數據映射成 model

extension ObservableType where E == Response {
public func mapModel<T: HandyJSON>(_ type: T.Type) -> Observable<T> {
return flatMap { response -> Observable<T> in
return Observable.just(response.mapModel(T.self))
}
}
}
 
extension Response {
func mapModel<T: HandyJSON>(_ type: T.Type) -> T {
let jsonString = String.init(data: data, encoding: .utf8)
return JSONDeserializer<T>.deserializeFrom(json: jsonString)!
}
}

 

文章轉載自  ,以做記錄


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM