iOS(swiftui)——网络连接(Moya)

Moya 是一个流行的 Swift 网络抽象层,被用于简化 iOS 应用程序中的网络请求。使用 Moya,可以定义网络请求的方式,增加类型安全性,因为所有的网络请求都是经过 Swift 类型系统检查的,并且 Moya 提供了一种很好的方式来将网络请求代码组织得更加清晰和可维护。

Moya 的核心是一个 TargetType 协议,它定义了一个 API 端点的所有必要信息,包括路径、方法、任务、HTTP 任务和可能的测试数据。开发者需要为所消费的每一个 API 端点创建一个符合 TargetType 协议的枚举 case。

官网:https://github.com/Moya/Moya/blob/master/Readme_CN.md

1. 首先在项目中添加Moya 依赖

xcode swiftui项目添加依赖-CSDN博客

2.定义网络通用模型

比如你的接口返回数据结构如下:

Swift 复制代码
{
 code:200,
 message:"成功",
 data:{}
}

定义一个BaseDetailResponse结构体为网络通用模型

Swift 复制代码
import HandyJSON

// 通用网络请求模型
struct BaseDetailResponse<T: HandyJSON>: HandyJSON {
    var code: Int?
    var message: String?
    var data: T?
}

3. 定义一个 TargetType 协议的枚举

Swift 复制代码
import Moya

enum RequestApi {
    //获取会议信息
    case getMeetingroom(meetingNum:Int)
}

// MARK: - 实现TargetType协议
extension RequestApi:TargetType{
    var sampleData: Data {
           switch self {
           case .getMeetingroom:
               return "{\"token\": \"sample token\"}".data(using: .utf8)!
           // 其他 API 请求的测试数据...
           case .getCaptions:
               return "{\"token\": \"sample token\"}".data(using: .utf8)!
           }
       }
    
    var baseURL: URL {
        let url = "域名"
        return URL(string: url)!
    }
    // 返回每个请求的路径
    var path: String {
        switch self{
        
            
        case .getMeetingroom:
            return "xx/xx"
        default:
            fatalError("Request path is null")
        }
        
    }
    
    var method: Moya.Method {
        switch self{
        case .getMeetingroom:
            return .post
        default:
            return.get
        }
    }
    
    var task: Moya.Task {
        switch self{
        
        case .getMeetingroom(let meetingNum):
            // 用于编码成x-www-form-urlencoded的参数
            let params: [String: Any] = ["meetingNum": meetingNum]
            return .requestParameters(parameters: params, encoding: URLEncoding.default)
       
        default:
            //不传递任何参数
            return .requestPlain
        
        }
        
    }
    /// 请求头
    var headers: [String : String]? {
        var headers:Dictionary<String,String> = [:]
        
        //内容的类型
        switch self{
        case .getMeetingroom:
            headers["Content-Type"]="application/x-www-form-urlencoded"
            break
        default:
            break
        }
        

        
        return headers
    }
}

4. 定义接口返回数据模型

若getMeetingroom返回数据结构为

Swift 复制代码
{
    meetingNum:4234234234,
    meetingName:"会议"
}

定义会议信息结构体

Swift 复制代码
struct MeetingInfo: HandyJSON {
    var meetingNum:Int
    var meetingName:String
    init() {
        self.meetingNum = 0
        self.meetingName = ""
    }
}

5. 初始化网络请求,发送请求

使用 MoyaProvider 来初始化网络请求,发送请求,并处理响应或者错误。

Swift 复制代码
//
//  DoRequest.swift
//


import Foundation
import Moya
import RxSwift
import HandyJSON

class DoRequest{
    static let shared = DoRequest()
    private var provider:MoyaProvider<RequestApi>!
    
    
    // MARK:
    func getMeetingroom(data:Int, completion: @escaping (BaseDetailResponse<MeetingInfo>?, Error?) -> ()) {
        provider.request(.getMeetingroom(meetingNum: data)){ result in
            switch result {
            case let .success(response):
                if let jsonResponse = BaseDetailResponse<MeetingInfo>.deserialize(from: String(data: response.data, encoding: .utf8)) {
                    completion(jsonResponse, nil)
                } else {
                    print("Decoding Error")
                    completion(nil, DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "Decoding error")))
                }
            case let .failure(error):
                print(error.errorDescription ?? "error")
                completion(nil, error)
            }
        }
    }
    /// 私有构造方法 主要为了打印后台请求到的数据 便于查看
    private init() {

        //网络请求加载对话框
        let networkActivityPlugin = NetworkActivityPlugin { change, target in
            //changeType类型是NetworkActivityChangeType
            //通过它能监听到开始请求和结束请求 //targetType类型是TargetType
            //就是我们这里的service //通过它能判断是那个请求
            if change == .began {
                //开始请求
                let targetType = target as! RequestApi
                switch targetType {
                case .getMeetingroom:
                    DispatchQueue.main.async {
                        //切换到主线程 才可以操作view
                    }
                default:
                    break
                }
            } else {
                //结束请求
                DispatchQueue.main.async {
                }
            }
        }
        plugins.append(networkActivityPlugin)
        provider = MoyaProvider<RequestApi>(plugins: plugins)
    }
}

5. 使用示例

Swift 复制代码
            let intValue = Int("4234234234")!
            let meetingInfo = MeetingInfo()
            DoRequest.shared.getMeetingroom(data: intValue) { (response, error) in
                if let response = response {
                    if let code = response.code{
                        if(code == 200){
                            // 处理你的响应
                            if let data = response.data {
                                // Use meetingRoomInfo here
                               meetingInfo = data
                                
                            }
                        }else{
                            self.alertMessage = response.message!
                            self.showAlert = true
                        }
                    }

                } else if let error = error {
                    //登录失败
                    self.showAlert = true
                    self.alertMessage = error.localizedDescription
                    return
                }
            }
相关推荐
小江村儿的文杰15 小时前
UE4 iOS Package的过程与XCode工程中没有游戏Content的原因
macos·ios·ue4·xcode
__WanG18 小时前
Flutter将应用打包发布到App Store
前端·flutter·ios
安和昂21 小时前
【iOS】bug调试技巧
ios·bug·cocoa
emperinter1 天前
WordCloudStudio Now Supports AliPay for Subscriptions !
人工智能·macos·ios·信息可视化·中文分词
AirDroid_cn1 天前
iPhone或iPad接收的文件怎么找?怎样删除?
ios·iphone·ipad·文件传输
Swift社区1 天前
在 Swift 中实现字符串分割问题:以字典中的单词构造句子
开发语言·ios·swift
#摩斯先生1 天前
Swift从0开始学习 对象和类 day3
ios·xcode·swift
没头脑的ht1 天前
Swift内存访问冲突
开发语言·ios·swift
#摩斯先生1 天前
Swift从0开始学习 并发性 day4
ios·xcode·swift
_黎明1 天前
【Swift】类型标注、类型安全和类型推断
swift