Swift(Moya+KakaJSON+PromiseKit) 網(wǎng)絡(luò)編程方案

app網(wǎng)絡(luò)請求封裝工具的實(shí)現(xiàn)缓呛,使用Moya+KakaJSON+PromiseKit,代碼如下:

創(chuàng)建Server配置http :

//
//  KoomeApi.swift
//  know
//
//  Created by Debug.s on 2022/4/26.
//

import Foundation
import Moya
import Alamofire
 
/// APP版本
public var appVersion: String {
    get {
        return "1.0.0"
    }
}

enum KoomeServer {
    //登陸
    case loginApp(params: [String: String])
    //注冊
    case register(params: [String: String])
    // 注冊保存用戶信息
    case registerUserInfo(params: [String: String])
}


extension KoomeServer : TargetType{
    
    var path: String {
        switch self{
        case .loginApp:
            return "/user/login"
        case .register:
            return "/user/register"
        case .registerUserInfo:
            return "/user/registerUserInfo"
        }
    }
    
    var method: Moya.Method {
        switch self{
        case .loginApp,.register:
            return .post
        case .registerUserInfo:
            return .get
        }
    }
    
    var task: Task {
        switch self{
        case .loginApp(let params),.register(let params),.registerUserInfo(let params):
            //參數(shù)加密
            let encyParams = KoomeRequest.share.encyDis(parameters: params)
            return  .requestParameters(parameters: encyParams, encoding: JSONEncoding.default)
//        default:
//            return .requestPlain
        }
        /*
         如果是圖片等資源文件上傳用這個(gè)
             let formData = MultipartFormData(provider: .data(imgDate), name: "file",
                                               fileName: "hangge.png", mimeType: "image/png")
             return .uploadCompositeMultipart([formData], urlParameters: parameters)
         */
    }
    
    var headers: [String : String]? {
        return [
            "h": appVersion,
            "Accept": "application/json",
            "Content-Type": "application/json",
            "Accept-Language": "en-US",
        ]
    }
     
    public var baseURL: URL {
        return URL(string: HttpURLType.user.url)!
    }
    
    
    var parameterEncoding: ParameterEncoding {
           return JSONEncoding.default // Send parameters as JSON in request body
       }
    
    var sampleData: Data {
           return "".data(using: .utf8)!
    }
}

創(chuàng)建請求主工具

//
//  KoomeRequest.swift
//  know
//
//  Created by Debug.s on 2022/4/26.
//

import Foundation
import Moya
import Alamofire
import PromiseKit
import KakaJSON

class KoomeRequest {
    
    static let share = KoomeRequest()
       
    //通過插件的方式監(jiān)聽網(wǎng)絡(luò)狀態(tài)
    let networkPlugin = NetworkActivityPlugin { (type,target) in
            switch type {
            case .began:
               print("顯示loading")
            case .ended:
                print("隱藏loading")
            }
      }
     
    /// 網(wǎng)絡(luò)請求的基本設(shè)置,這里可以拿到是具體的哪個(gè)網(wǎng)絡(luò)請求葫男,可以在這里做一些設(shè)置
    private let endpointClosure = {(target: TargetType) -> Endpoint in
        let url = target.baseURL.absoluteString + target.path
        var task = target.task
        var endPoint = Endpoint(url: url,
                                sampleResponseClosure: { .networkResponse(200, target.sampleData) },
                                method: target.method,
                                task: task,
                                httpHeaderFields: target.headers)
        if let apiTarget = target as? MultiTarget,
           let tar = apiTarget.target as? KoomeServer  {
            print(tar)
        }
        return endPoint
    }
    /// 網(wǎng)絡(luò)請求的設(shè)置
    private let requestClosure = { (endpoint: Endpoint, done: MoyaProvider<KoomeServer>.RequestResultClosure) in
        do {
            var request = try endpoint.urlRequest()
            // 設(shè)置請求時(shí)長
            request.timeoutInterval = 20
            // 打印請求參數(shù)
            if let requestData = request.httpBody {
                print("請求的url:\(request.url!)" + "\n" + "\(request.httpMethod ?? "")" + "發(fā)送參數(shù)" + "\(String(data: request.httpBody!, encoding: String.Encoding.utf8) ?? "")")
            } else {
                print("請求的url:\(request.url!)" + "\(String(describing: request.httpMethod))")
            }
            if let header = request.allHTTPHeaderFields {
                print("請求頭內(nèi)容\(header)")
            }
            done(.success(request))
        } catch {
            done(.failure(MoyaError.underlying(error, nil)))
        }
    }
    
    //參數(shù)加密
    public func encyDis(parameters:[String: String]) -> [String: String]{
        return  paramsEncrypt(parameters)!
    }
    //請求方法
    public func request<T: Convertible>(api:KoomeServer) -> Promise<RequestResultModel<T>> {
        return Promise<RequestResultModel<T>> { resolver in
            //設(shè)置moya 配置
            let provider = MoyaProvider<KoomeServer>(endpointClosure: endpointClosure, requestClosure: requestClosure, plugins: [networkPlugin], trackInflights: false)
            provider.request(api) { result in
                switch result{
                case .success(let response):
                    // 解析數(shù)據(jù)
                    if let json = try? response.mapJSON() {
                        // 解析json
                        let resultModel: RequestResultModel<T> = self.parsingJson(json as! [String : Any])
                              // 后臺(tái)code!=200, 走錯(cuò)誤處理
                              guard resultModel.isSuccess else {
                                  if resultModel.code == "-5" {
                                      // 臨時(shí)token過期code
                                      resolver.reject(RequestError(code: resultModel.code, data: resultModel.data, message: resultModel.msg))
                                  } else if resultModel.code == "-6" {
                                      // 禁用code
                                  } else if resultModel.code == "-9" {
                                      // 踢蹬code
                                  } else {
                                      resolver.reject(RequestError(code: resultModel.code, data: resultModel.data, message: resultModel.msg))
                                  }
                                  return
                              }
                              // 返回model
                              resolver.fulfill(resultModel)
                    } else {
                        resolver.reject(RequestError(code: RequestErrorType.parsing.rawValue, data: "", message: "Data parsing error"))
                    }
                
                case .failure(let error):
                    debugPrint(error)
                   resolver.reject(RequestError(code: RequestErrorType.network.rawValue, data: "", message: "Network request error"))
                    break
                }
            }
        }
    }
    
    
    /// 參數(shù)加密
    private func paramsEncrypt(_ parameters: Any? = nil) -> [String: String]? {
        
//        removerHeaders(name: "sign")
        
        // rsa加密
        if let params = parameters,
           let jsonStr = CommonUtil.jsonStr(obj: params),
           let encryptStr = EncryptUtil.encryptRSA(str: jsonStr) {
            return ["sign": encryptStr]
        }
        
        return [:]
    }
    
    /// 解析json
    private func parsingJson<T: Convertible>(_ json: [String: Any]) -> RequestResultModel<T> {
        
        let resultModel = json.kj.model(RequestResultModel<T>.self)
        if stringIsEmpty(str: resultModel.data) {
            return resultModel
        }
        
        // 解密
        let key = EncryptUtil.decryptAES128(str: resultModel.sign) ?? ""
        var decryptStr = EncryptUtil.decryptDES(str: resultModel.data, key: key) ?? ""
        if decryptStr.hasPrefix("\"") && decryptStr.hasSuffix("\"") {
            if let i = decryptStr.firstIndex(of: "\"") {
                decryptStr.remove(at: i)
            }
            if let i = decryptStr.lastIndex(of: "\"") {
                decryptStr.remove(at: i)
            }
        }
        
        resultModel.data = decryptStr
        resultModel.pasringModel()
        
        #if DEBUG
        if let obj = CommonUtil.jsonObject(json: decryptStr) {
            PLog(obj)
        }
        #endif
        
        return resultModel
    }
    
}

如果app分多個(gè)人多個(gè)模塊可以使用甘有,模塊化管理接口,比如 用戶登陸棍现、首頁为黎、我的邮丰,這邊舉例 創(chuàng)建一個(gè)用戶請求, 傳入要解析的model

RequestResultModel 長這樣

class RequestResultModel<T: Convertible>{
   var code = ""
    /// 解密后的json, 如果T是RequestStringModel則是后臺(tái)返回的參數(shù)
    var data = ""
    var msg = ""
    var sign = "" 
    /// 解析數(shù)據(jù)格式[key: value]
    var model: T?
    /// 解析數(shù)據(jù)格式[[key: value]]
    var modelArray: [T]?

  /// 把json解析成model
    func pasringModel() {
        // RequestStringModel 字符串?dāng)?shù)據(jù)不必再解析, 數(shù)據(jù)在data
        guard !stringIsEmpty(str: data),
              T.self != RequestStringModel.self else {
            return
        }
        // 解析model或者modelArray
        let obj = CommonUtil.jsonObject(json: data)
        if obj is [String: Any] {
            model = data.kj.model(T.self)
        } else if obj is [[String: Any]] {
            modelArray = data.kj.modelArray(T.self)
        }
    }
}
//
//  KoomeUserRequest.swift
//  know
//
//  Created by Debug.s on 2022/4/26.
//

import Foundation
import PromiseKit
class KoomeUserRequest{
    /// 注冊
    static public func register(code: String, emailAccount: String, password: String) -> Promise<RequestResultModel<RequestStringModel>> {
        
        let params: [String: String] = [
            "device": UIDevice.current.name,
            "deviceId": UIDevice.current.identifierForVendor?.uuidString ?? "",
            "code": code,
            "emailAccount": emailAccount,
            "password": password.md5()
        ]
        return  KoomeRequest.share.request(api: .registerUserInfo(params: params))
    }

}

使用

 KoomeUserRequest.register(code: "1234", emailAccount: "3899379@qq.com", password: "1234qwer").done { result in
            
            //在這邊處理 result 邏輯

        }.catch { _ in
            
        }.finally {
            
        }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市铭乾,隨后出現(xiàn)的幾起案子剪廉,更是在濱河造成了極大的恐慌,老刑警劉巖炕檩,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件斗蒋,死亡現(xiàn)場離奇詭異,居然都是意外死亡笛质,警方通過查閱死者的電腦和手機(jī)泉沾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來妇押,“玉大人跷究,你說我怎么就攤上這事∏没簦” “怎么了俊马?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長肩杈。 經(jīng)常有香客問我柴我,道長,這世上最難降的妖魔是什么扩然? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任艘儒,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘界睁。我一直安慰自己觉增,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布翻斟。 她就那樣靜靜地躺著抑片,像睡著了一般。 火紅的嫁衣襯著肌膚如雪杨赤。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天截汪,我揣著相機(jī)與錄音疾牲,去河邊找鬼。 笑死衙解,一個(gè)胖子當(dāng)著我的面吹牛阳柔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蚓峦,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼舌剂,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了暑椰?” 一聲冷哼從身側(cè)響起霍转,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎一汽,沒想到半個(gè)月后避消,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡召夹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年岩喷,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片监憎。...
    茶點(diǎn)故事閱讀 40,040評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡纱意,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鲸阔,到底是詐尸還是另有隱情偷霉,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布隶债,位于F島的核電站腾它,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏死讹。R本人自食惡果不足惜瞒滴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧妓忍,春花似錦虏两、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至旁瘫,卻和暖如春祖凫,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背酬凳。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工惠况, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人宁仔。 一個(gè)月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓稠屠,卻偏偏與公主長得像,于是被迫代替她去往敵國和親翎苫。 傳聞我的和親對象是個(gè)殘疾皇子权埠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評論 2 355

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