Alamofire + Moya 網(wǎng)絡請求

1. 網(wǎng)絡管理工具類的封裝:

import UIKit
import Moya
import Alamofire
import SwiftyJSON

class NetworkManager: NSObject {

    ///成功數(shù)據(jù)的回調(diào)
    typealias successCallback = ((JSON) -> (Void))
    ///失敗的回調(diào)
    typealias failedCallback = ((String) -> (Void))
    ///網(wǎng)絡錯誤的回調(diào)
    typealias errorCallback = (() -> (Void))

     // https://github.com/Moya/Moya/blob/master/docs/Providers.md  參數(shù)使用說明
     /// 最常用的網(wǎng)絡請求攘宙,只需知道正確的結(jié)果無需其他操作時候用這個 (可以給調(diào)用的NetWorkReques方法的寫參數(shù)默認值達到一樣的效果,這里為解釋方便做抽出來二次封裝)
     ///
     /// - Parameters:
     ///   - target: 網(wǎng)絡請求
     ///   - completion: 請求成功的回調(diào)
    static  func NetWorkRequest(_ target: WebAPI, completion: @escaping successCallback){
         NetWorkRequest(target, completion: completion, failed: nil, errorResult: nil)
     }

     /// 需要知道成功或者失敗的網(wǎng)絡請求讲仰, 要知道code碼為其他情況時候用這個 (可以給調(diào)用的NetWorkRequest方法的參數(shù)默認值達到一樣的效果,這里為解釋方便做抽出來二次封裝)
     ///
     /// - Parameters:
     ///   - target: 網(wǎng)絡請求
     ///   - completion: 成功的回調(diào)
     ///   - failed: 請求失敗的回調(diào)
    static  func NetWorkRequest(_ target: WebAPI, completion: @escaping successCallback , failed:failedCallback?) {
         NetWorkRequest(target, completion: completion, failed: failed, errorResult: nil)
     }

     ///  需要知道成功吓妆、失敗鹰霍、錯誤情況回調(diào)的網(wǎng)絡請求   像結(jié)束下拉刷新各種情況都要判斷
     ///
     /// - Parameters:
     ///   - target: 網(wǎng)絡請求
     ///   - completion: 成功
     ///   - failed: 失敗
     ///   - error: 錯誤
     @discardableResult //當我們需要主動取消網(wǎng)絡請求的時候可以用返回值Cancellable, 一般不用的話做忽略處理
     static func NetWorkRequest(_ target: WebAPI, completion: @escaping successCallback , failed:failedCallback?, errorResult:errorCallback?) -> Cancellable? {
         //先判斷網(wǎng)絡是否有鏈接 沒有的話直接返回--代碼略
         if !isNetworkConnect{
             print("提示用戶網(wǎng)絡似乎出現(xiàn)了問題")
             return nil
         }

         ////網(wǎng)絡請求發(fā)送的核心初始化方法鸽斟,創(chuàng)建網(wǎng)絡請求對象
         let Provider = MoyaProvider<WebAPI>(endpointClosure: myEndpointClosure, requestClosure: requestClosure, plugins: [networkPlugin], trackInflights: false)

         //這里顯示loading圖
         return Provider.request(target) { (result) in
             //隱藏hud
             switch result {
             case let .success(response):
                 do {
                     let jsonData = try JSON(data: response.data)
                     completion(jsonData)
                     //print(jsonData)
                     //               這里的completion和failed判斷條件依據(jù)不同項目來做琢歇,為演示demo我把判斷條件注釋了育韩,直接返回completion擦酌。

                     //completion(String(data: response.data, encoding: String.Encoding.utf8)!)

                     //print("flag不為1000 HUD顯示后臺返回message"+"\(jsonData[RESULT_MESSAGE].stringValue)")

                     //                if jsonData[RESULT_CODE].stringValue == "1000"{
                     //                    completion(String(data: response.data, encoding: String.Encoding.utf8)!)
                     //                }else{
                     //                    failed?(String(data: response.data, encoding: String.Encoding.utf8)!)
                     //                }

                 } catch {

                 }
             case let .failure(error):
                 //網(wǎng)絡連接失敗,提示用戶
                 print("網(wǎng)絡連接失敗\(error)")
                 errorResult?()
             }
         }
     }

     /// 基于Alamofire,網(wǎng)絡是否連接垂攘,這個方法不建議放到這個類中,可以放在全局的工具類中判斷網(wǎng)絡鏈接情況
     /// 用get方法是因為這樣才會在獲取isNetworkConnect時實時判斷網(wǎng)絡鏈接請求维雇,如有更好的方法可以fork
     static var isNetworkConnect: Bool {
         get{
             let network = NetworkReachabilityManager()
             return network?.isReachable ?? true //無返回就默認網(wǎng)絡已連接
         }
     }

    ///網(wǎng)絡請求的基本設置,這里可以拿到是具體的哪個網(wǎng)絡請求,可以在這里做一些設置
    static let myEndpointClosure = { (target: WebAPI) -> Endpoint in
        ///這里把endpoint重新構(gòu)造一遍主要為了解決網(wǎng)絡請求地址里面含有? 時無法解析的bug https://github.com/Moya/Moya/issues/1198
        let url = target.baseURL.absoluteString + target.path
        var task = target.task

        /*
         如果需要在每個請求中都添加類似token參數(shù)的參數(shù)請取消注釋下面代碼
         ??????????????????????????????????????????????????
         */
    //    let additionalParameters = ["token":"888888"]
    //    let defaultEncoding = URLEncoding.default
    //    switch target.task {
    //        ///在你需要添加的請求方式中做修改就行晒他,不用的case 可以刪掉吱型。。
    //    case .requestPlain:
    //        task = .requestParameters(parameters: additionalParameters, encoding: defaultEncoding)
    //    case .requestParameters(var parameters, let encoding):
    //        additionalParameters.forEach { parameters[$0.key] = $0.value }
    //        task = .requestParameters(parameters: parameters, encoding: encoding)
    //    default:
    //        break
    //    }
        /*
         ??????????????????????????????????????????????????
         如果需要在每個請求中都添加類似token參數(shù)的參數(shù)請取消注釋上面代碼
         */

        var endpoint = Endpoint(
            url: url,
            sampleResponseClosure: { .networkResponse(200, target.sampleData) },
            method: target.method,
            task: task,
            httpHeaderFields: target.headers
        )
        return endpoint
    }

    ///網(wǎng)絡請求的設置
    static let requestClosure = { (endpoint: Endpoint, done: MoyaProvider.RequestResultClosure) in
        do {
            var request = try endpoint.urlRequest()
            //設置請求時長
            request.timeoutInterval = 30
            // 打印請求參數(shù)
            if let requestData = request.httpBody {
                print("\(request.url!)"+"\n"+"\(request.httpMethod ?? "")"+"發(fā)送參數(shù)"+"\(String(data: request.httpBody!, encoding: String.Encoding.utf8) ?? "")")
            }else{
                print("\(request.url!)"+"\(String(describing: request.httpMethod))")
            }
            done(.success(request))
        } catch {
            done(.failure(MoyaError.underlying(error, nil)))
        }
    }

    /// NetworkActivityPlugin插件用來監(jiān)聽網(wǎng)絡請求陨仅,界面上做相應的展示
    ///但這里我沒怎么用這個津滞。。灼伤。 loading的邏輯直接放在網(wǎng)絡處理里面了
    static let networkPlugin = NetworkActivityPlugin.init { (changeType, targetType) in
        print("networkPlugin \(changeType)")
        //targetType 是當前請求的基本信息
        switch(changeType){
        case .began:
            print("開始請求網(wǎng)絡")

        case .ended:
            print("結(jié)束")
        }
    }

    /*   設置ssl
    let policies: [String: ServerTrustPolicy] = [
        "example.com": .pinPublicKeys(
            publicKeys: ServerTrustPolicy.publicKeysInBundle(),
            validateCertificateChain: true,
            validateHost: true
        )
    ]
}

2. moya的設置

import Foundation
import Moya

/// 定義基礎域名
let Moya_baseURL = "http://api.liwushuo.com/"

enum WebAPI{

    case getPhotoList//獲取圖片列表

    case updateAPi(parameters:[String:Any])
    case register(email:String,password:String)
    case uploadHeadImage(parameters: [String:Any],imageDate:Data)//上傳用戶頭像
}

extension WebAPI : TargetType {

    var baseURL: URL {
        switch self {
        case .getPhotoList:
            return URL.init(string:(Moya_baseURL))!
        default:
            return URL.init(string:(Moya_baseURL))!
        }
    }

    var path: String {

        switch self {

        case .getPhotoList:
            return "v2/channels/104/items?ad=2&gender=2&generation=2&limit=20&offset=0"

        case .register:
            return "register"

        case .updateAPi:
            return "versionService.getAppUpdateApi"

        case .uploadHeadImage:
            return "/file/user/upload.jhtml"
        }
    }

    var method: Moya.Method {
        switch self {
        case .getPhotoList:
            return .get
        default:
            return .post
        }
    }

    //    這個是做單元測試模擬的數(shù)據(jù)触徐,必須要實現(xiàn),只在單元測試文件中有作用
    var sampleData: Data {
        return "".data(using: String.Encoding.utf8)!
    }

    //    該條請API求的方式,把參數(shù)之類的傳進來
    var task: Task {
//        return .requestParameters(parameters: nil, encoding: JSONArrayEncoding.default)
        switch self {

        case .getPhotoList:
            return .requestPlain

        case let .register(email, password):
            return .requestParameters(parameters: ["email": email, "password": password], encoding: JSONEncoding.default)

        case let .updateAPi(parameters):
            return .requestParameters(parameters: parameters, encoding: URLEncoding.default)

        //圖片上傳
        case .uploadHeadImage(let parameters, let imageDate):
            ///name 和fileName 看后臺怎么說狐赡,   mineType根據(jù)文件類型上百度查對應的mineType
            let formData = MultipartFormData(provider: .data(imageDate), name: "file",
                                              fileName: "hangge.png", mimeType: "image/png")
            return .uploadCompositeMultipart([formData], urlParameters: parameters)

        //可選參數(shù)https://github.com/Moya/Moya/blob/master/docs_CN/Examples/OptionalParameters.md
        }
    }

    var headers: [String : String]? {
        return ["Content-Type":"application/x-www-form-urlencoded"]
    }

}

3. 實際應用

import UIKit
import Alamofire
import SwiftyJSON
import Kingfisher
import HandyJSON

// 相當于數(shù)據(jù)模型model
struct ItemsModel: HandyJSON {

    var cover_image_url = ""
    var title  = ""
    var likecount = ""
}

class SwiftyJSON_HandyJson_VC: UIViewController,UITableViewDelegate,UITableViewDataSource {

    lazy var gifttableview: UITableView = {
        let tableview: UITableView = UITableView(frame:self.view.bounds, style: .plain)
        tableview.backgroundColor = .white
        tableview.delegate = self
        tableview.dataSource = self
        tableview.rowHeight = 300

        return tableview
    }()

    // 數(shù)據(jù)源
    var dataArray = [ItemsModel]()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.navigationItem.title = "SwiftyJSON_HandyJson的使用"

        self.view.addSubview(gifttableview)
        self.AlamofireGetRequest()
        //self.AlamofirePostRequest()
        //注冊cell
        gifttableview.register(SamTableViewCell.self)
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.dataArray.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCell(with: SamTableViewCell.self, for: indexPath)
        let model = self.dataArray[indexPath.row]
        cell.iconImv.kf.setImage(with: URL(string: model.cover_image_url))
        return cell
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
         print(indexPath.row)
    }
}

extension SwiftyJSON_HandyJson_VC{

    func AlamofireGetRequest() {

        NetworkManager.NetWorkRequest(.getPhotoList, completion: { (JSOnDictory) -> (Void) in//JSOnDictory 是Json類型
            //print(json)
            let dataARR =  JSOnDictory["data"]["items"].arrayObject
            if let arr = JSONDeserializer<ItemsModel>.deserializeModelArrayFrom(array: dataARR) {
                let arr1 = arr.compactMap({$0})
                self.dataArray = arr1
                self.gifttableview.reloadData()
            }
        }) { (errorStr) -> (Void) in
            print(errorStr)
        }
    }

}

作者:coder_xiang
鏈接:http://www.reibang.com/p/3442a3b7cf53
著作權(quán)歸作者所有撞鹉。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市颖侄,隨后出現(xiàn)的幾起案子鸟雏,更是在濱河造成了極大的恐慌,老刑警劉巖发皿,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件崔慧,死亡現(xiàn)場離奇詭異,居然都是意外死亡穴墅,警方通過查閱死者的電腦和手機惶室,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來玄货,“玉大人皇钞,你說我怎么就攤上這事∷勺剑” “怎么了夹界?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長隘世。 經(jīng)常有香客問我可柿,道長,這世上最難降的妖魔是什么丙者? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任复斥,我火速辦了婚禮,結(jié)果婚禮上械媒,老公的妹妹穿的比我還像新娘目锭。我一直安慰自己评汰,他們只是感情好,可當我...
    茶點故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布痢虹。 她就那樣靜靜地躺著被去,像睡著了一般。 火紅的嫁衣襯著肌膚如雪奖唯。 梳的紋絲不亂的頭發(fā)上惨缆,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天,我揣著相機與錄音臭埋,去河邊找鬼踪央。 笑死,一個胖子當著我的面吹牛瓢阴,可吹牛的內(nèi)容都是我干的畅蹂。 我是一名探鬼主播,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼荣恐,長吁一口氣:“原來是場噩夢啊……” “哼液斜!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起叠穆,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤少漆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后硼被,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體示损,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年嚷硫,在試婚紗的時候發(fā)現(xiàn)自己被綠了检访。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡仔掸,死狀恐怖脆贵,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情起暮,我是刑警寧澤卖氨,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站负懦,受9級特大地震影響筒捺,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜纸厉,卻給世界環(huán)境...
    茶點故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一焙矛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧残腌,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至闺金,卻和暖如春逾滥,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背败匹。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工寨昙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人掀亩。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓舔哪,卻偏偏與公主長得像,于是被迫代替她去往敵國和親槽棍。 傳聞我的和親對象是個殘疾皇子捉蚤,可洞房花燭夜當晚...
    茶點故事閱讀 43,658評論 2 350

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