網(wǎng)絡(luò)請求框架Moya使用一

一、安裝 Moya(CocoaPods)

pod "Moya/RxSwift”

pod “HandyJSON”

二话侧、基本用法

1语淘、實現(xiàn)? TargetType? 協(xié)議

2、實現(xiàn)? PluginType 插件協(xié)議

3孩革、擴展 ObservableType 解析 JSON 數(shù)據(jù)

//MoyaProvider

import Foundation

import Moya

//Provider

let requestProvider = MoyaProvider<RequestManagerProvider>(plugins: [RequestLoadingPlugin()])

//Hud?Provider

let requestHudProvider = MoyaProvider<RequestManagerProvider>(plugins: [RequestLoadingPlugin(true)])

enum RequestManagerProvider {

????//密碼登錄

????case LoginPassword(mobile:String, password:String)

????//注冊

????case Register(mobile:String, password: String, code: String)

????//忘記密碼

????case ForgetPassword(mobile:String, code: String, password: String, repassword: String)

}

extension RequestManagerProvider: TargetType {


????var baseURL: URL {

????????return URL(string: "http://baseurl.com")!

????}


????//請求路徑

????var path: String {

????????switch self {

????????case .LoginPassword:

????????????return "/login"

????????case .Register:

????????????return "/register"

????????case .ForgetPassword:

????????????return "/forgetpwd"

????????}

????}

????//請求方式

????var method: Moya.Method {

????????return .post

????}


????//用于單元測試

????var sampleData: Data {

????????return "".data(using: String.Encoding.utf8)!

????}


????//請求接口時對應(yīng)的請求參數(shù)

????var task: Task {


????????switch self {

????????case .LoginPassword(let mobile,let password):


????????????let bundleId = Bundle.main.bundleIdentifier!


????????????let formData1 = MultipartFormData(provider: .data(mobile.data(using: .utf8)!), name: "mobile")

????????????let formData2 = MultipartFormData(provider: .data(password.data(using: .utf8)!), name: "password")

????????????let formData3 = MultipartFormData(provider: .data(bundleId.data(using: .utf8)!), name: "bundle_id")

????????????return .uploadMultipart([formData1, formData2,formData3])


????????case .Register(let mobile, let password, let code):


????????????let bundleId = Bundle.main.bundleIdentifier!


????????????let formData1 = MultipartFormData(provider: .data(mobile.data(using: .utf8)!), name: "mobile")

????????????let formData2 = MultipartFormData(provider: .data(password.data(using: .utf8)!), name: "password")

????????????let formData3 = MultipartFormData(provider: .data(code.data(using: .utf8)!), name: "code")

????????????let formData4 = MultipartFormData(provider: .data(bundleId.data(using: .utf8)!), name: "bundle_id")


????????????return .uploadMultipart([formData1, formData2, formData3, formData4])

????????case .ForgetPassword(let mobile, let code, let password, let repassword):


????????????let formData1 = MultipartFormData(provider: .data(mobile.data(using: .utf8)!), name: "mobile")

????????????let formData2 = MultipartFormData(provider: .data(password.data(using: .utf8)!), name: "newpassword")

????????????let formData3 = MultipartFormData(provider: .data(code.data(using: .utf8)!), name: "code")

????????????let formData4 = MultipartFormData(provider: .data(repassword.data(using: .utf8)!), name: "repassword")

? ? ? ? ? ? return .uploadMultipart([formData1, formData2, formData3, formData4])

????????case .VerificationCode(let mobile, let event):

????????????let formData1 = MultipartFormData(provider: .data(mobile.data(using: .utf8)!), name: "mobile")

????????????let formData2 = MultipartFormData(provider: .data(event.data(using: .utf8)!), name: "event")

????????????return .uploadMultipart([formData1, formData2])

????????case .RouteList:


????????????let typeid = Bundle.main.bundleIdentifier! == "com.shanhushanhu.shanhushanhu" ? "1" : "2"


????????????let formData1 = MultipartFormData(provider: .data(typeid.data(using: .utf8)!), name: "typeid")

????????????return .uploadMultipart([formData1])

? ? ? ? default:

????????????return .requestPlain

? ? ? ? }

????}

? ? //header信息

????var headers: [String : String]? {

????????return ["Content-Type":"multipart/form-data"]

????}

}

//請求插件

import Foundation

import Moya

import iProgressHUD

class RequestLoadingPlugin: PluginType {


????var SwiftIsShowHud:Bool = false


????init(_ isShowHud: Bool = false) {

????????SwiftIsShowHud = isShowHud

????}



????func prepare(_ request: URLRequest, target: TargetType) -> URLRequest {

????????print("prepare")

????????var mRequest = request

????????mRequest.timeoutInterval = 20

????????return mRequest

????}

????func willSend(_ request: RequestType, target: TargetType) {

????????print("開始請求")

????????if SwiftIsShowHud == true {


????????????DispatchQueue.main.async {

????????????????let keyViewController = UIApplication.shared.keyWindow?.rootViewController

????????????????if (keyViewController != nil) {


????????????????????iProgressHUD.sharedInstance().attachProgress(toView: (keyViewController!.view)!)

????????????????????keyViewController!.view.showProgress()

????????????????}

????????????}

????????}


????}


????func didReceive(_ result: Result<Response, MoyaError>, target: TargetType) {

????????print("結(jié)束請求")


????????if SwiftIsShowHud == true {

????????????DispatchQueue.main.async {

????????????????let keyViewController = UIApplication.shared.keyWindow?.rootViewController

????????????????if (keyViewController != nil) {

????????????????????keyViewController!.view.dismissProgress()

????????????????}

????????????}

????????}


//????????switch result {

//????????case .failure(let error):

//

//????????????let errorReason: String = error.errorDescription ?? ""

//????????????var tip = ""

//????????????if errorReason.contains("The Internet connection appears to be offline") {

//????????????????tip = "網(wǎng)絡(luò)不給力岁歉,請檢查您的網(wǎng)絡(luò)"

//????????????}else if errorReason.contains("Could not connect to the server") {

//????????????????tip = "無法連接服務(wù)器"

//????????????}else {

//????????????????tip = "請求失敗"

//????????????}

//

//????????default:

//????????????break

//????????}

????}

}

//JSON 解析

import Foundation

import RxSwift

import HandyJSON

import Moya

enum DCUError : Swift.Error {

????case ParseJSONError

????case RequestFailed

????case NoResponse

????case UnexpectedResult(resultCode: Int?,resultMsg:String?)

}

enum RequestStatus: Int {

????case requestSuccess = 1

????case requestTokenError = 401

????case requestError

}

fileprivate let RESULT_CODE = "code"

fileprivate let RESULT_MSG = "msg"

fileprivate let RESULT_DATA = "data"

public extension ObservableType {

????func mapResponseToObject<T: HandyJSON>(type: T.Type) -> Observable<T> {

????????return map { response in

????????????guard let response = response as? Moya.Response

????????????????else {

????????????????????throw DCUError.NoResponse

????????????}

//????????????guard ((200...209) ~= response.statusCode) else {

//????????????????throw DCUError.RequestFailed

//????????????}

????????????////////////////////////////////////////////////////////////

//????????????let jsonData = try response.mapJSON() as! [String : Any]

//????????????if let code = jsonData[RESULT_CODE] as? String {

//????????????????if code == "查詢成功" {

//????????????????????if let model = JSONDeserializer<T>.deserializeFrom(dict: jsonData){

//????????????????????????return model

//????????????????????}

//????????????????}

//????????????}

????????????////////////////////////////////////////////////////////////

????????????guard let json = try?JSONSerialization.jsonObject(with: response.data, options: .mutableContainers) as? [String:Any] else {

????????????????throw DCUError.NoResponse

????????????}????????????


????????????if let code = json[RESULT_CODE] as? Int {

????????????????if code == RequestStatus.requestSuccess.rawValue {

????????????????????let data = json[RESULT_DATA]


????????????????????let objects = JSONDeserializer<T>.deserializeFrom(dict: data as? Dictionary)


????????????????????if objects != nil {

????????????????????????return objects!

????????????????????}


????????????????????if let data = data as? Data {

????????????????????????let jsonString = String(data: data,encoding: .utf8)

????????????????????????let object = JSONDeserializer<T>.deserializeFrom(json: jsonString)



????????????????????????if object != nil {

????????????????????????????return object!

????????????????????????}else {

????????????????????????????return T()

//????????????????????????????throw DCUError.ParseJSONError

????????????????????????}

????????????????????}else {

????????????????????????return T()

//????????????????????????throw DCUError.ParseJSONError

????????????????????}

????????????????}else if code == RequestStatus.requestTokenError.rawValue {

????????????????????// Tocken失效 跳轉(zhuǎn)登錄

????????????????????VPNUserManager.sharedInstance().removeUserInfo()

????????????????????NotificationCenter.default.post(name: NotificationName_Login, object: nil)


????????????????????throw DCUError.UnexpectedResult(resultCode:json[RESULT_CODE] as? Int, resultMsg: nil)

????????????????}else {

????????????????????throw DCUError.UnexpectedResult(resultCode:json[RESULT_CODE] as? Int, resultMsg: json[RESULT_MSG] as? String)

????????????????}

????????????}else {

????????????????throw DCUError.ParseJSONError

????????????}


????????}

????}


????func mapResponseToObjectArray<T: HandyJSON>(type: T.Type) -> Observable<[T]> {

????????return map { response in


????????????// 得到response

????????????guard let response = response as? Moya.Response else {

????????????????throw DCUError.NoResponse

????????????}


????????????// 檢查狀態(tài)碼

//????????????guard ((200...209) ~= response.statusCode) else {

//????????????????throw DCUError.RequestFailed

//????????????}


????????????guard let json = try? JSONSerialization.jsonObject(with: response.data, options: JSONSerialization.ReadingOptions(rawValue: 0)) as? [String: Any]??else {

????????????????throw DCUError.NoResponse

????????????}


????????????// 服務(wù)器返回code

????????????if let code = json[RESULT_CODE] as? Int {

????????????????if code == RequestStatus.requestSuccess.rawValue {

????????????????????guard let objectsArrays = json[RESULT_DATA] as? NSArray else {

????????????????????????throw DCUError.ParseJSONError

????????????????????}

????????????????????// 使用HandyJSON解析成對象數(shù)組

????????????????????if let objArray = JSONDeserializer<T>.deserializeModelArrayFrom(array: objectsArrays) {

????????????????????????if let objectArray: [T] = objArray as? [T] {

????????????????????????????return objectArray

????????????????????????}else {

????????????????????????????return [T]()

????????????????????????}

????????????????????}else {

????????????????????????return [T]()

????????????????????}


????????????????}else if code == RequestStatus.requestTokenError.rawValue {

????????????????????// Tocken失效 跳轉(zhuǎn)登錄

????????????????????VPNUserManager.sharedInstance().removeUserInfo()

????????????????????NotificationCenter.default.post(name: NotificationName_Login, object: nil)

????????????????????return [T]()

????????????????} else {

????????????????????throw DCUError.UnexpectedResult(resultCode: json[RESULT_CODE] as? Int , resultMsg: json[RESULT_MSG] as? String)


????????????????}

????????????} else {

????????????????throw DCUError.ParseJSONError

????????????}

????????}

????}

}

//調(diào)用

requestProvider.rx.request(.LoginPassword(mobile: mobile, password: password)).asObservable()

????????????????.mapResponseToObject(type: VPNLoginResultMode.self)

????????????????.subscribe(onNext: { (model) in


?????????????????????self.view.dismissProgress()


????????????????????if let token = model.userinfo?.token {

????????????????????????VPNUserManager.sharedInstance().saveUserInfo(mobile: mobile,tocken: token)


????????????????????????GYHUD.flash(.success, title: "登錄成功", onView: self.view, delay: 1) {


????????????????????????????self.dismiss(animated: true) {}

????????????????????????}

????????????????????}

????????????????},onError: { (error) in

????????????????????self.view.dismissProgress()


????????????????????switch error {

????????????????????case DCUError.UnexpectedResult(_,let resultMsg):

????????????????????????if let msg = resultMsg { GYHUD.flash(.label, title: msg, onView: self.view, delay: 1.5) }

????????????????????default:

????????????????????????GYHUD.flash(.label, title: "請求網(wǎng)絡(luò)失敗!", onView: self.view, delay: 1.5)

????????????????????}


????????????????}).disposed(by: disposeBag)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市膝蜈,隨后出現(xiàn)的幾起案子锅移,更是在濱河造成了極大的恐慌,老刑警劉巖饱搏,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件非剃,死亡現(xiàn)場離奇詭異,居然都是意外死亡推沸,警方通過查閱死者的電腦和手機备绽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進店門券坞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人肺素,你說我怎么就攤上這事恨锚。” “怎么了倍靡?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵猴伶,是天一觀的道長。 經(jīng)常有香客問我塌西,道長他挎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任捡需,我火速辦了婚禮办桨,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘站辉。我一直安慰自己呢撞,他們只是感情好,可當我...
    茶點故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布庵寞。 她就那樣靜靜地躺著狸相,像睡著了一般。 火紅的嫁衣襯著肌膚如雪捐川。 梳的紋絲不亂的頭發(fā)上脓鹃,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天,我揣著相機與錄音古沥,去河邊找鬼瘸右。 笑死,一個胖子當著我的面吹牛岩齿,可吹牛的內(nèi)容都是我干的太颤。 我是一名探鬼主播,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼盹沈,長吁一口氣:“原來是場噩夢啊……” “哼龄章!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起乞封,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤做裙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后肃晚,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锚贱,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年关串,在試婚紗的時候發(fā)現(xiàn)自己被綠了拧廊。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片监徘。...
    茶點故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖吧碾,靈堂內(nèi)的尸體忽然破棺而出凰盔,到底是詐尸還是另有隱情,我是刑警寧澤滤港,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布廊蜒,位于F島的核電站趴拧,受9級特大地震影響溅漾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜著榴,卻給世界環(huán)境...
    茶點故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一添履、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧脑又,春花似錦暮胧、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至严卖,卻和暖如春席舍,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背哮笆。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工来颤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人稠肘。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓福铅,卻偏偏與公主長得像,于是被迫代替她去往敵國和親项阴。 傳聞我的和親對象是個殘疾皇子滑黔,可洞房花燭夜當晚...
    茶點故事閱讀 44,573評論 2 353