動態

詳情 返回 返回

RxSwift+Moya+Alamofire構建網絡層 - 動態 詳情

最近又把 RxSwift複習了下,寫了一個小 Demo 主要是構建網路模塊,Demo 我已經上傳,在文章末尾處可以下載,接下來就一步步去構建:

第一步(數據層):使用 ObjectMapper 構建 Model

//
//  LoginModel.swift
//  RxSwiftDemo01
//
//  Created by macOSJack on 2024/11/5.
//

import Foundation
import ObjectMapper

class LoginModel:Mappable{
    
    var username:String?
    var password:String?
    
    required init?(map: ObjectMapper.Map) {}
    
    func mapping(map: ObjectMapper.Map) {
        username<-map["username"]
        password<-map["password"]
    }
    
    
}

(網絡層)第二步:接口, IP 請求配置

//
//  api.swift
//  RxSwiftDemo01
//
//  Created by macOSJack on 2024/11/5.
//

import Foundation
import Moya

let ApiProvider = Moya.MoyaProvider<APi>(plugins: [RequestLoadingPlugin()])

//
enum APi{
    case login
    case changepassword
}


let apiTask = ApiTask()

extension APi:TargetType{
    var baseURL: URL {
        return URL.init(string: "http://localhost:8080/SpringMVC")!
    }
    
    var path: String {
        switch self{
        case .login:
            return "/user/login"
        case .changepassword:
            return "/changePsd"
        default:
            return "/"
            break;
        }
    }
    
    var method: Moya.Method {
        switch self{
        case .login,.changepassword:
            return .post
        default:
            return .get
        }
    }
    
    var task: Moya.Task {
        switch self{
        case .login:
            return apiTask.login(username: "jack", password: "123")
        case.changepassword:
            return apiTask.changePsd(oldPsd: "123", newPsd: "456")
        }
    }
    
    var headers: [String : String]? {
        return ["Content-Type":"application/x-www-form-urlencoded"]
    }
    
    
    var sampleData: Data{
        
        return "{username:'sdsds',password:'8246343'}".data(using: String.Encoding.utf8)!
    }
    
}

第三步:網絡請求任務

//
//  Task.swift
//  RxSwiftDemo01
//
//  Created by macOSJack on 2024/11/5.
//

import Foundation
import Moya

class ApiTask:NSObject{
    func login(username:String,password:String) -> Moya.Task {
        return Moya.Task
        .requestParameters(parameters: ["username":username,"password":password], encoding: URLEncoding.default)
        
//            .requestData(jsonToData(jsonDic: ["username":username,"password":password], target: APi.login)!)
    }
    
    func changePsd(oldPsd:String,newPsd:String) -> Moya.Task {
        Moya.Task.requestData(jsonToData(jsonDic: ["oldPsd":oldPsd,"newPsd":newPsd], target: APi.changepassword)!)
    }
    
    private func jsonToData(jsonDic:Dictionary<String,Any>,target:APi)->Data?{
        if !JSONSerialization.isValidJSONObject(jsonDic){
            print("it's not json!")
        }
        let data = try? JSONSerialization.data(withJSONObject: jsonDic, options: JSONSerialization.WritingOptions.prettyPrinted)
        let jsonStr = String(data: data!, encoding: String.Encoding.utf8)
        print("\(target)--->json:\(jsonStr)")
        return data
        
    }
    
    private func jsonToString(jsonDic:Dictionary<String,Any>,target:APi)->String?{
        if !JSONSerialization.isValidJSONObject(jsonDic){
            print("it's not json!")
        }
        let data = try? JSONSerialization.data(withJSONObject: jsonDic, options: JSONSerialization.WritingOptions.prettyPrinted)
        let jsonStr = String(data: data!, encoding: String.Encoding.utf8)
        print("\(target)--->json:\(jsonStr)")
        return jsonStr
        
    }
}

第四步:網絡請求組件

//
//  RequestuserLoadingPlugin.swift
//  RxSwiftDemo01
//
//  Created by macOSJack on 2024/11/5.
//

import Foundation
import Moya
import Result
import ObjectMapper
import RxSwift
import RxCocoa

class RequestLoadingPlugin:PluginType{
    func prepare(_ request: URLRequest, target: TargetType) -> URLRequest {
        var myRequest = request
        myRequest.timeoutInterval = 20.0
        return myRequest
    }
    
    
    func willSend(_ request: RequestType, target: TargetType) {
        print("開始請求\(request)")
    }
    
    func didReceive(_ result: Result<Response, MoyaError>, target: TargetType) {
        print("結束請求\(target)")
        switch result{
        case .success(let response):
            print(String(data: response.data, encoding: String.Encoding.utf8))
            break
        case .failure(let moyaErr):
            print("請求失敗:\(moyaErr.localizedDescription)")
            break
        }
    }
}

extension Observable{
    func mapObject<T:Mappable>(type:T.Type) -> Observable<T> {
        return self.map{
            response in
            guard let dic = response as? [String:Any] else
            {
                throw RxSwiftMoyaError.ParseJsonError
            }
            return Mapper<T>().map(JSON: dic["data"] as! [String:Any])!
        }
    }
    
    func mapArray<T:Mappable>(type:T.Type) -> Observable<[T]> {
        return self.map{
            response in
            guard let array = response as? [Any] else{
                throw RxSwiftMoyaError.OtherError
            }
            guard let dicArr = array as? [[String:Any]] else{
                throw RxSwiftMoyaError.ParseJsonError
            }
            return Mapper<T>().mapArray(JSONArray: dicArr)
        }
    }
}

enum RxSwiftMoyaError:String{
    case ParseJsonError
    case OtherError
}

extension RxSwiftMoyaError:Swift.Error{}

第五步:Moya+RxSwift 構建 ViewModel 層

//
//  LoginViewModel.swift
//  RxSwiftDemo01
//
//  Created by macOSJack on 2024/11/5.
//

import Foundation
import Moya
import RxSwift

class LoginViewModel:NSObject{
    func login() -> Observable<LoginModel> {
        return ApiProvider.rx.request(.login).filterSuccessfulStatusCodes().asObservable().mapJSON().mapObject(type: LoginModel.self)
    }
}

到此為止,一個簡易的網絡請求層構建好了.

user avatar densen2014 頭像 sue0604 頭像 xiaofeixiang_63ec941cad48a 頭像 aitaokedemugua 頭像 someonelikeyou 頭像 debugly 頭像 MrYU4 頭像 djz1234 頭像 daoshanghundesijidou 頭像 jzxstudio 頭像 GarveyCalvin 頭像 mano 頭像
點贊 15 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.