(alamofire + moya )網(wǎng)絡(luò)請(qǐng)求 + Swiftyjson + HandyJson的實(shí)際應(yīng)用

(alamofire + moya )網(wǎng)絡(luò)請(qǐng)求 + Swiftyjson + HandyJson的實(shí)際應(yīng)用

附上我的swfit項(xiàng)目, 項(xiàng)目里面有整個(gè)swift應(yīng)用使用框架, (alamofire + moya )網(wǎng)絡(luò)請(qǐng)求 + Swiftyjson + HandyJson的實(shí)際應(yīng)用, DSBridge原生與H5交互的用法, 反射知識(shí)的使用, WCDB數(shù)據(jù)庫的封裝使用, WebRTC音視頻直播demo, socket的使用, socket協(xié)議的封裝使用等等知識(shí)點(diǎn). 希望對(duì)大家有用.-->swfit完整項(xiàng)目2020持續(xù)更新完善

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

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)絡(luò)錯(cuò)誤的回調(diào)
    typealias errorCallback = (() -> (Void))
    
    
     // https://github.com/Moya/Moya/blob/master/docs/Providers.md  參數(shù)使用說明
     /// 最常用的網(wǎng)絡(luò)請(qǐng)求,只需知道正確的結(jié)果無需其他操作時(shí)候用這個(gè) (可以給調(diào)用的NetWorkReques方法的寫參數(shù)默認(rèn)值達(dá)到一樣的效果,這里為解釋方便做抽出來二次封裝)
     ///
     /// - Parameters:
     ///   - target: 網(wǎng)絡(luò)請(qǐng)求
     ///   - completion: 請(qǐng)求成功的回調(diào)
    static  func NetWorkRequest(_ target: WebAPI, completion: @escaping successCallback){
         NetWorkRequest(target, completion: completion, failed: nil, errorResult: nil)
     }

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

     ///  需要知道成功漠烧、失敗祠斧、錯(cuò)誤情況回調(diào)的網(wǎng)絡(luò)請(qǐng)求   像結(jié)束下拉刷新各種情況都要判斷
     ///
     /// - Parameters:
     ///   - target: 網(wǎng)絡(luò)請(qǐng)求
     ///   - completion: 成功
     ///   - failed: 失敗
     ///   - error: 錯(cuò)誤
     @discardableResult //當(dāng)我們需要主動(dòng)取消網(wǎng)絡(luò)請(qǐng)求的時(shí)候可以用返回值Cancellable, 一般不用的話做忽略處理
     static func NetWorkRequest(_ target: WebAPI, completion: @escaping successCallback , failed:failedCallback?, errorResult:errorCallback?) -> Cancellable? {
         //先判斷網(wǎng)絡(luò)是否有鏈接 沒有的話直接返回--代碼略
         if !isNetworkConnect{
             print("提示用戶網(wǎng)絡(luò)似乎出現(xiàn)了問題")
             return nil
         }
         
         ////網(wǎng)絡(luò)請(qǐng)求發(fā)送的核心初始化方法领迈,創(chuàng)建網(wǎng)絡(luò)請(qǐng)求對(duì)象
         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ù)不同項(xiàng)目來做压彭,為演示demo我把判斷條件注釋了运翼,直接返回completion双谆。
                     
                     //completion(String(data: response.data, encoding: String.Encoding.utf8)!)
                     
                     //print("flag不為1000 HUD顯示后臺(tái)返回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)絡(luò)連接失敗壳咕,提示用戶
                 print("網(wǎng)絡(luò)連接失敗\(error)")
                 errorResult?()
             }
         }
     }


     /// 基于Alamofire,網(wǎng)絡(luò)是否連接,這個(gè)方法不建議放到這個(gè)類中,可以放在全局的工具類中判斷網(wǎng)絡(luò)鏈接情況
     /// 用get方法是因?yàn)檫@樣才會(huì)在獲取isNetworkConnect時(shí)實(shí)時(shí)判斷網(wǎng)絡(luò)鏈接請(qǐng)求顽馋,如有更好的方法可以fork
     static var isNetworkConnect: Bool {
         get{
             let network = NetworkReachabilityManager()
             return network?.isReachable ?? true //無返回就默認(rèn)網(wǎng)絡(luò)已連接
         }
     }

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

        /*
         如果需要在每個(gè)請(qǐng)求中都添加類似token參數(shù)的參數(shù)請(qǐng)取消注釋下面代碼
         ??????????????????????????????????????????????????
         */
    //    let additionalParameters = ["token":"888888"]
    //    let defaultEncoding = URLEncoding.default
    //    switch target.task {
    //        ///在你需要添加的請(qǐng)求方式中做修改就行,不用的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
    //    }
        /*
         ??????????????????????????????????????????????????
         如果需要在每個(gè)請(qǐng)求中都添加類似token參數(shù)的參數(shù)請(qǐng)取消注釋上面代碼
         */
    
        var endpoint = Endpoint(
            url: url,
            sampleResponseClosure: { .networkResponse(200, target.sampleData) },
            method: target.method,
            task: task,
            httpHeaderFields: target.headers
        )
        return endpoint
    }

    ///網(wǎng)絡(luò)請(qǐng)求的設(shè)置
    static let requestClosure = { (endpoint: Endpoint, done: MoyaProvider.RequestResultClosure) in
        do {
            var request = try endpoint.urlRequest()
            //設(shè)置請(qǐng)求時(shí)長(zhǎng)
            request.timeoutInterval = 30
            // 打印請(qǐng)求參數(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)絡(luò)請(qǐng)求,界面上做相應(yīng)的展示
    ///但這里我沒怎么用這個(gè)熊痴。替裆。甫匹。 loading的邏輯直接放在網(wǎng)絡(luò)處理里面了
    static let networkPlugin = NetworkActivityPlugin.init { (changeType, targetType) in
        print("networkPlugin \(changeType)")
        //targetType 是當(dāng)前請(qǐng)求的基本信息
        switch(changeType){
        case .began:
            print("開始請(qǐng)求網(wǎng)絡(luò)")
            
        case .ended:
            print("結(jié)束")
        }
    }

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

2. moya的設(shè)置

import Foundation
import Moya


/// 定義基礎(chǔ)域名
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
        }
    }

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

    //    該條請(qǐng)API求的方式,把參數(shù)之類的傳進(jìn)來
    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 看后臺(tái)怎么說场晶,   mineType根據(jù)文件類型上百度查對(duì)應(yīng)的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. 實(shí)際應(yīng)用

import UIKit
import Alamofire
import SwiftyJSON
import Kingfisher
import HandyJSON


// 相當(dāng)于數(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()
        //注冊(cè)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)
        }
    }

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末度宦,一起剝皮案震驚了整個(gè)濱河市琳钉,隨后出現(xiàn)的幾起案子菠剩,更是在濱河造成了極大的恐慌,老刑警劉巖鄙煤,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晾匠,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡梯刚,警方通過查閱死者的電腦和手機(jī)混聊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人句喜,你說我怎么就攤上這事预愤。” “怎么了咳胃?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵植康,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我展懈,道長(zhǎng)销睁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任存崖,我火速辦了婚禮冻记,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘来惧。我一直安慰自己冗栗,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布供搀。 她就那樣靜靜地躺著隅居,像睡著了一般。 火紅的嫁衣襯著肌膚如雪葛虐。 梳的紋絲不亂的頭發(fā)上胎源,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音屿脐,去河邊找鬼涕蚤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛的诵,可吹牛的內(nèi)容都是我干的万栅。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼奢驯,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼申钩!你這毒婦竟也來了次绘?” 一聲冷哼從身側(cè)響起瘪阁,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎邮偎,沒想到半個(gè)月后管跺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡禾进,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年豁跑,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片泻云。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡艇拍,死狀恐怖狐蜕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情卸夕,我是刑警寧澤层释,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站快集,受9級(jí)特大地震影響贡羔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜个初,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一乖寒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧院溺,春花似錦楣嘁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至弄息,卻和暖如春痊班,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背摹量。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工涤伐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人缨称。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓凝果,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親睦尽。 傳聞我的和親對(duì)象是個(gè)殘疾皇子器净,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

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