如在OC中使用AFNetworking通常,Swift咱們用Alamofire來作網絡庫.而Moya在Alamofire的基礎上又封裝了一層:
ios
官方說moya
有如下特性-_-:github
就像這樣:json
enum APIManager { case getNewsLatest//獲取最新消息 case getStartImage// 啓動界面圖像獲取 case getVersion(String)//軟件版本查詢 case getThemes//主題日報列表查看 case getNewsDetail(Int)//獲取新聞詳情 }
TargetType
協議就像這樣:api
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等.網絡
Moya
的使用很是簡單,經過TargetType
協議定義好每一個target
以後,就能夠直接使用Moya
開始發送網絡請求了。就像這樣:閉包
let provider = MoyaProvider<APIManager>() provider.request(.getNewsLatest) { result in // do something with result }
Moya
自己已是一個使用起來很是方便,可以寫出很是簡潔優雅的代碼的網絡封裝庫,可是讓Moya
變得更增強大的緣由之一還由於它對於Functional Reactive Programming
的擴展,具體說就是對於RxSwift
和ReactiveCocoa
的擴展,經過與這兩個庫的結合,能讓Moya
變得更增強大。我選擇RxSwift
的緣由有兩個,一個是RxSwift
的庫相對來講比較輕量級,語法更新相對來講比較少,我以前用過ReactiveCocoa
,一些大版本的更新需求重寫不少代碼,第二個更重要的緣由是由於RxSwift
背後有整個ReactiveX
的支持,裏面包括Java
,JS
,.Net
, Swift
,Scala
,它們內部都用了ReactiveX
的邏輯思想,這意味着你一旦學會了其中的一個,之後能夠很快的上手ReactiveX
中的其餘語言。app
Moya
提供了很是方面的RxSwift
擴展:ide
let provider = RxMoyaProvider<APIManager>() provider.request(.getNewsLatest) .filterSuccessfulStatusCodes() .mapJSON() .subscribe(onNext: { (json) in //do something with posts print(json) }) .addDisposableTo(disposeBag)
解釋一下:post
RxMoyaProvider
是MoyaProvider
的子類,是對RxSwift
的擴展
filterSuccessfulStatusCodes()
是Moya
爲RxSwift
提供的擴展方法,顧名思義,能夠獲得成功地網絡請求,忽略其餘的
mapJSON()
也是Moya RxSwift
的擴展方法,能夠把返回的數據解析成 JSON
格式
subscribe
是一個RxSwift
的方法,對通過一層一層處理的 Observable
訂閱一個 onNext
的 observer
,一旦獲得 JSON
格式的數據,就會經行相應的處理
addDisposableTo(disposeBag)
是 RxSwift
的一個自動內存處理機制,跟ARC
有點相似,會自動清理不須要的對象。
在實際應用過程當中網絡請求每每緊密鏈接着數據層(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)! } }
文章轉載自 Three_Zhang's Blog ,以作記錄