swift4.0 -Moya使用(包含批量上傳圖片,請求出錯或者業(yè)務統(tǒng)一處理)

學習目的

我只是出于對于這個框架的好奇,曾經(jīng)我在學習swift的時候,就是用的Alamofire,突然發(fā)現(xiàn)有一個很優(yōu)雅的第三方是基于這個向上封裝。并且,我很久沒有寫swift了。

功能

本文包含了Moya的基本使用和圖片批量上傳(視頻等其它文件上傳跟圖片上傳類似)。并且應用泛型實現(xiàn)了對返回結(jié)果統(tǒng)一做出處理,便于統(tǒng)一處理一些業(yè)務或者錯誤。

  • 實現(xiàn)協(xié)議

LoginAPIManager文件包含一個登陸的請求,一個批量上傳圖片的請求(單張請自行做修改)。分別傳入了對應的參數(shù),小伙伴可以根據(jù)自己需求去寫這個枚舉。
這里啰嗦一下,請求的manager請做好分類,這樣找起來會方便很多,根據(jù)功能,或者根據(jù)模塊等都可以。

public enum LoginAPIManager {
    case login(name:String,password:String) //登錄
    case uploadPictures(paramsDic:NSMutableDictionary,dataAry:NSArray)  //上傳圖片
}

實現(xiàn)TargetType協(xié)議內(nèi)容,代碼中注釋很清楚了哈。

extension LoginAPIManager: TargetType {
    public var baseURL: URL {
        return URL(string: kBaseUrl)!   //這里是aip的base
    }
    
    public var path: String {
        switch self {
        case .login(_, _):
            return "登陸請求api"  //(這里請寫上自己的api哦)
        case .uploadPictures(_, _):
            return "上傳圖片api"  //(這里請寫上自己的api哦)
        }
       
    }
    //請求方式
    public var method: Moya.Method {
        return .post
    }

    //請求任務事件,帶上參數(shù)
    public var task: Task {
        switch self {
        case .login( let name, let password):
            return .requestParameters(parameters: ["userAccount": name,"initialPassword" : password], encoding: JSONEncoding.default)
        case .uploadPictures( let paramsDic, let dataAry):
            let formDataAry:NSMutableArray = NSMutableArray()
            for (index,image) in dataAry.enumerated() {
                //圖片轉(zhuǎn)成Data
                let data:Data = UIImageJPEGRepresentation(image as! UIImage, 0.9)!
                //根據(jù)當前時間設置圖片上傳時候的名字
                let date:Date = Date()
                let formatter = DateFormatter()
                formatter.dateFormat = "yyyy-MM-dd-HH:mm:ss"
                var dateStr:String = formatter.string(from: date as Date)
                //別忘記這里給名字加上圖片的后綴哦
                dateStr = dateStr.appendingFormat("-%i.png", index)
                
                let formData = MultipartFormData(provider: .data(data), name: "file", fileName: dateStr, mimeType: "image/jpeg")
                formDataAry.add(formData)
            }
            return .uploadCompositeMultipart(formDataAry as! [MultipartFormData], urlParameters: paramsDic as! [String : Any])
//        default:
//            return .requestPlain    // 沒有參數(shù)
        }
    }
    
    //是否執(zhí)行Alamofire驗證
//    public var validate: Bool {
//        return false
//    }
    
    //驗證方式
    public var validationType: ValidationType {
        return .none
    }

    //這個就是做單元測試模擬的數(shù)據(jù),只會在單元測試文件中有作用
    public var sampleData: Data {
        return "{}".data(using: String.Encoding.utf8)!
    }
    
    //請求頭
    public var headers: [String: String]? {
        return nil
    }
}
  • 泛型實現(xiàn)返回結(jié)果統(tǒng)一處理

這里的endpointMapping是為了便于出錯的情況下,清楚的知道這個請求的相關信息。

EDBaseAdapter這個文件,是用來對于請求的返回值,做統(tǒng)一處理的。在這個文件的
上層做一些緊密業(yè)務的處理,這里可以拋出問題和做一些大家共同需要處理的業(yè)務或者錯誤。

例如:這里可以做,如果你的項目session過期了,要統(tǒng)一彈出登錄頁面。還有業(yè)務出錯,錯誤碼的解析,都可以放在這個文件里面。

這里實現(xiàn)思路是用泛型的概念,傳了枚舉作為參數(shù)的方法,生成一個實現(xiàn)了TargetType協(xié)議的類,從而去調(diào)用request方法。

這里的泛型我理解了很久,因為我不知道為什么我傳了一個LoginAPIManager里面的枚舉對象,就可以生成一個LoginAPIManager的Provider。后來我這樣理解,雖然我傳入的是一個LoginAPIManager的枚舉,但是實際上在生成MoyaProvider,用到的是LoginAPIManager實現(xiàn)的TargetType協(xié)議,枚舉泛指著LoginAPIManager這個類。個人理解,可能會不對哈。

private func endpointMapping<Target: TargetType>(target: Target) -> Endpoint {
    
    print("請求連接:\(target.baseURL)\(target.path) \n方法:\(target.method)\n參數(shù):\(String(describing: target.task)) ")
    return MoyaProvider.defaultEndpointMapping(for: target)
}
class EDBaseAdapter:NSObject {
    
    class func  request<T:TargetType>(
        _ target:T,success successCallback: @escaping (Any) -> Void,
        error errorCallback: @escaping (Int,String ) -> Void,
        failure failureCallback: @escaping (MoyaError) -> Void
        ) {
        let provider = MoyaProvider<T>(endpointClosure: endpointMapping,plugins:[])
        provider.request(target) { (result) in
        switch result {
            case let .success(response):
                do {
                    let data = try response.mapJSON()
                    let statusCode = response.statusCode
                    //在我的項目里,200和201是請求成功。
                    if (statusCode == 201 || statusCode == 200) {
                        //解析登錄數(shù)據(jù)
                        print("請求成功")
                        successCallback(data)
                    } else {
                        //請求報錯提示,一般處理業(yè)務提示
                        print("請求出錯了")
                        let dict = data
                        errorCallback(statusCode,(dict as AnyObject).object(forKey:"message") as! String)
                    }
                } catch {
                    //可不做處理
                }
                break
            case let .failure(error):
                print(error)
                failureCallback(error)
                break
            }
        }
    }
}

請求調(diào)用

下面的方法,我自己寫完測試,是可以獲取到數(shù)據(jù)的。

        //登錄調(diào)用
        EDBaseAdapter.request(LoginAPIManager.login(name: self.userNameTextField.text!, password: self.passwordTextField.text!), success: { (data) in
            print(data)
        }, error: { (statutCode, message) in
            print(statutCode,message)
        }) { (error) in
            print(error)
        }
        
        //上傳圖片調(diào)用
        let paramsDic:NSMutableDictionary = NSMutableDictionary()
        paramsDic.setValue(0, forKey: "projectType")
        EDBaseAdapter.request(LoginAPIManager.uploadPictures(paramsDic: paramsDic, dataAry:NSArray.init(object: UIImage.init(named: "example")!)), success: { (data) in
            print(data)
        }, error: { (statutCode, message) in
            print(statutCode,message)
        }) { (error) in
            print(error)
        }

結(jié)尾

如果有什么問題或者疑問,請告知我。可能我回復慢,或者不及時請諒解一下呢。但是態(tài)度絕對是很端正的。還有,妹子還是寫OC的,swift邊寫邊學,不懂的再找資料。所以,描述或者用詞不準確,請諒解同時請告知我,我看到會及時更正。希望能夠一起學習和一起進步。
有一個簡單的工程,里面包含了這些文件。是我隨手寫的一個登陸的界面,登錄事件里面調(diào)用了文中登錄和上傳圖片的方法。
鏈接:https://pan.baidu.com/s/132XqsEzdEV0q0A2SiIdbJQ 密碼:0m51

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,967評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,273評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,870評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,742評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,527評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,010評論 1 322
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,108評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,250評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,769評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,656評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,853評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,371評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,103評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,472評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,717評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,487評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,815評論 2 372

推薦閱讀更多精彩內(nèi)容