最近又把 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)
    }
}

到此为止,一个简易的网络请求层构建好了.


脚踏实地一点一滴
1 声望1 粉丝

我们都是非常平凡之人,没有家庭背景,没有强大后台,没有八面玲珑的人脉,更没有天选之子的才能,唯一能靠的只有自己。