Moya架構圖
Moya架構圖
CocoaPods集成
pod 'RxCocoa'
pod 'RxSwift'
pod 'Moya/RxSwift'
pod 'HandyJSON'
Moya簡單使用
1.定義枚舉撕氧,存儲網絡請求
// 定義一個枚舉,存放我們的網絡請求
enum MemberApi {
case login(username:String,password:String,token:String)
}
2. 實現(xiàn)moya的TargetType協(xié)議
extension MemberApi:TargetType{
//api 接口基地址
var baseURL: URL {
return URL.init(string: BaseURL)!
}
//請求路徑
var path:String{
switch self {
case .login(username: _, password:_ , token:_):
return "login/accountLogin"
}
}
var headers: [String: String]? {
return nil;
}
//請求的參數(shù)
var parameters: [String: Any]? {
switch self {
case .login(username: let userName, password: let pwd, token: let token):
return ["account":userName,"pwd":pwd,"deviceToken":token];
}
}
///請求方式
var method: Moya.Method {
switch self {
case .login(username: _, password: _, token: _):
return .post;
}
}
/// 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)!
}
//MARK:task type
var task: Task {
return .requestPlain
}
var validate: Bool {
return false
}
}
3. 發(fā)起網絡請求
let provider = MoyaProvider<MemberApi>();
provider.request(.login(username: "haha", password: "123456", token: "qwe")) { (result) in
if result.error == nil{
LLog(result.value);
}
}
模型轉換
首先, 我們需要處理Moya請求返回Moya.Response對象, 在返回給客戶端時我們需要將Moya.Response映射成相應的模型對象再扭。
其次, 我們希望使用RxSwift的鏈式寫法來完成字典到模型的轉換夜矗。
基于如上兩點: 我們需要做如下兩步處理泛范。
1.擴展RxSwift 的 Observable 協(xié)議給其添加mapModel方法,傳入要映射的模型類型
2.需要將Moya.Response對象映射成相應的模型對象紊撕,這里配合使用HandyJSON庫
代碼如下:
///定義在處理過程中可能出現(xiàn)的Error
enum RxSwiftMoyaError: String {
case ParseJSONError ///解析json時出錯
case OtherError ///其他錯誤
case ResponseError ///返回的結果有錯
case RequestFailedError ///請求返回錯誤 (根據(jù)請求碼判斷)
}
///讓其實現(xiàn)Swift.Error 協(xié)議
extension RxSwiftMoyaError: Swift.Error { }
///擴展 RxSwift的Observable協(xié)議罢荡,添加mapModel方法
extension Observable {
func mapModel<T: HandyJSON>(_ type: T.Type) throws -> Observable<T> {
return map { response in
///判斷Response類型
guard let response = response as? Moya.Response else {
throw RxSwiftMoyaError.ResponseError
}
///判斷請求碼
guard (200...209) ~= response.statusCode else {
throw RxSwiftMoyaError.RequestFailedError
}
///轉json
guard let json = try? JSONSerialization.jsonObject(with: response.data, options: JSONSerialization.ReadingOptions.init(rawValue: 0)) as! [String: Any] else {
throw RxSwiftMoyaError.ResponseError
}
///使用HandyJSON庫,映射成指定模型
let object = JSONDeserializer<T>.deserializeFrom(dict: json)
guard let model = object else {
throw RxSwiftMoyaError.ParseJSONError
}
return model
}
}
}
使用:
///初始化一個MoyaProvider, 其中MemberApi為使用了TargetType協(xié)議的enum枚舉
let mp = MoyaProvider<MemeberApi>()
let ob = mp
.rx.request(type) /// rx.request 為Moya/RxSwift 庫中提供的擴展實現(xiàn),返回的是一個Single類型
.asObservable() ///需要使用asObservable將Single類型轉成Observable
.mapModel(UserInfo.self) ///將請求返回結果進行映射
網絡請求的處理過程大致如上区赵,代碼中只有有網絡請求的地方就會有如下代碼惭缰,所以這塊代碼的調用我們再把它封裝一下。
final class NetworkTools {
static func request<H: HandyJSON, T: TargetType>(_ type:T, _ model: H.Type) -> Observable<H> {
let mp = MoyaProvider<T>()
let ob = mp
.rx.request(type) ///type 實現(xiàn)T類型協(xié)議的具體對象
.asObservable()
.mapModel(model)
return ob
}
}
///使用
NetworkTools.request(MemberApi.login(username: "haha", password: "123456", token: "qwe"), UserInfo.self)
.subscribe(onNext:{ ///訂閱
})
最后
針對網絡層的封裝笼才,在如下的Demo中又做了演進漱受,如果感興趣,請移步至項目 TestProject 中查看