iOS 使用Moya网络请求
Moya最新版本11.0.2
由于前段时间写了这篇文章,最新Moya已更新最新版本,故此也更新了下用法,本人已使用,故特意奉上最新的使用demo供参考。 Moya11.0.2Demo
Moya简介
Moya 是你的 app 中缺失的网络层。不用再去想在哪儿(或者如何)安放网络请求,Moya 替你管理。
Moya 有几个比较好的特性:
- 编译时检查正确的API端点访问.* 使你定义不同端点枚举值对应相应的用途更加明晰.* 提高测试地位从而使单元测试更加容易.Swift我们用Alamofire来做网络库.而Moya在Alamofire的基础上又封装了一层,如下流程图说明Moya的简单工作流程图:
Moya的官方下载地址点我强大的Moya,有具体的使用方法在demo里面有说明。
本文主要介绍一下Moya的用法
- 设置请求头部信息
- 设置超时时间
- 自定义插件
- 自签名证书
注意:以下所出现的NetAPIManager跟官网上demo的** GitHub**是一样类型的文件,都是这个enum实现一个协议TargetType,点进去可以看到TargetType定义了我们发送一个网络请求所需要的东西,什么baseURL,parameter,method等一些计算性属性,我们要做的就是去实现这些东西,当然有带默认值的我们可以不去实现,但是设置头部信息跟超时时间就要修改这些系统默认设置了。
为了看得更加清楚,贴上NetAPIManager文件的内容
//
//NetAPIManager.swift
//NN110
//
//Created by 陈亦海 on 2017/5/12.
//Copyright © 2017年 陈亦海. All rights reserved.
//import Foundation
import Moyaenum NetAPIManager {case Showcase upload(bodyData: Data)case downloadcase request(isTouch: Bool, body: Dictionary<String, Any>? ,isShow: Bool)
}extension NetAPIManager: TargetType {var baseURL: URL {//服务器地址switch self {case .request( _, _, _):return URL(string: "https://www.pmphmall.com")<img src="https://httpbin.org")!}}var path: String {//具体某个方法的路径switch self {case .Show:return ""case .upload(_):return ""case .request(_, _, _):return "/app/json.do"case .download:return ""}}var method: Moya.Method {//请求的方法 get或者post之类的switch self {case .Show:return .getcase .request(_, _, _):return .postdefault:return .post}}var parameters: [String: Any]? {//请求的get post给服务器的参数switch self {case .Show:return nilcase .request(_, _, _):return ["msg":"H4sIAAAAAAAAA11SSZJFIQi7EqPAEgTvf6TP62W7sMoSQhKSWDrs6ZUKVWogLwYV7RjHFBZJlNlzloN6LVqID4a+puxqRdUKVNLwE1TRcZIC/fjF2rPotuXmb84r1gMXbiASZIZbhQdKEewJlz41znDkujCHuQU3dU7G4/PmVRnwArMLXukBv0J23XVahNO3VX35wlgce6TLUzzgPQJFuHngAczl6VhaNXpmRLxJBlMml6gdLWiXxTdO7I+iEyC7XuTirCQXOk4dotgArgkH/InxVjfNTnE/uY46++hyAiLFuFL4cv1Z8WH5DgB2GnvFXMh5gm53Tr13vqqrEYtcdXfkNsMwKB+9sAQ77grNJmquFWOhfXA/DELlMB0KKFtHOc/ronj1ml+Z7qas82L3VWiCVQ+HEitjTVzoFw8RisFN/jJxBY4awvq427McXqnyrfCsl7oeEU6wYgW9yJtj1lOkx0ELL5Fw4z071NaVzRA9ebxWXkFyothgbB445cpRmTC+//F73r1kOyQ3lTpec12XNDR00nnq5/YmJItW3+w1z27lSOLqgVctrxG4xdL9WVPdkH1tkiZ/pUKBGhADAAA="]default:return nil}}var sampleData: Data { //编码转义 return "{}".data(using: String.Encoding.utf8)!}var task: Task { //一个请求任务事件switch self {case let .upload(data):return .upload(.multipart([MultipartFormData(provider: .data(data), name: "file", fileName: "gif.gif", mimeType: "image/gif")]))default:return .request } }var parameterEncoding: ParameterEncoding {//编码的格式switch self {case .request(_, _, _):return URLEncoding.defaultdefault:return URLEncoding.default}}//以下两个参数是我自己写,用来控制网络加载的时候是否允许操作,跟是否要显示加载提示,这两个参数在自定义插件的时候会用到var touch: Bool { //是否可以操作switch self {case .request(let isTouch, _, _):return isTouchdefault:return false}}var show: Bool { //是否显示转圈提示switch self {case .request( _, _,let isShow):return isShowdefault:return false}}}" style="margin: auto" />
如何设置Moya请求头部信息
头部信息的设置在开发过程中很重要,如服务器生成的token,用户唯一标识等 我们直接上代码,不说那么多理论的东西,哈哈
// MARK: - 设置请求头部信息
let myEndpointClosure = { (target: NetAPIManager) -> Endpoint<NetAPIManager> inlet url = target.baseURL.appendingPathComponent(target.path).absoluteStringlet endpoint = Endpoint<NetAPIManager>(url: url,sampleResponseClosure: { .networkResponse(200, target.sampleData) },method: target.method,parameters: target.parameters,parameterEncoding: target.parameterEncoding)//在这里设置你的HTTP头部信息return endpoint.adding(newHTTPHeaderFields: ["Content-Type" : "application/x-www-form-urlencoded","ECP-COOKIE" : ""])}
如何设置请求超时时间
// MARK: - 设置请求超时时间
let requestClosure = { (endpoint: Endpoint<NetAPIManager>, done: @escaping MoyaProvider<NetAPIManager>.RequestResultClosure) inguard var request = endpoint.urlRequest else { return }request.timeoutInterval = 30//设置请求超时时间done(.success(request))
}
自定义插件
自定义插件必须PluginType协议的两个方法willSend与didReceive
//
//MyNetworkActivityPlugin.swift
//NN110
//
//Created by 陈亦海 on 2017/5/10.
//Copyright © 2017年 CocoaPods. All rights reserved.
//import Foundation
import Result
import Moya/// Network activity change notification type.
public enum MyNetworkActivityChangeType {case began, ended
}/// Notify a request's network activity changes (request begins or ends).
public final class MyNetworkActivityPlugin: PluginType {public typealias MyNetworkActivityClosure = (_ change: MyNetworkActivityChangeType, _ target: TargetType) -> Voidlet myNetworkActivityClosure: MyNetworkActivityClosurepublic init(newNetworkActivityClosure: @escaping MyNetworkActivityClosure) {self.myNetworkActivityClosure = newNetworkActivityClosure}// MARK: Plugin/// Called by the provider as soon as the request is about to startpublic func willSend(_ request: RequestType, target: TargetType) {myNetworkActivityClosure(.began,target)}/// Called by the provider as soon as a response arrives, even if the request is cancelled.public func didReceive(_ result: Result<Moya.Response, MoyaError>, target: TargetType) {myNetworkActivityClosure(.ended,target)}
}
使用自定义插件方法
// MARK: - 自定义的网络提示请求插件
let myNetworkPlugin = MyNetworkActivityPlugin { (state,target) inif state == .began {//SwiftSpinner.show("Connecting...")let api = target as! NetAPIManagerif api.show {print("我可以在这里写加载提示")}if !api.touch {print("我可以在这里写禁止用户操作,等待请求结束")}print("我开始请求\(api.touch)")UIApplication.shared.isNetworkActivityIndicatorVisible = true} else {//SwiftSpinner.show("request finish...")//SwiftSpinner.hide()print("我结束请求")UIApplication.shared.isNetworkActivityIndicatorVisible = false}
}
自签名证书
在16年的WWDC中,Apple已表示将从2017年1月1日起,**所有新提交的App必须强制性应用HTTPS协议来进行网络请求。**默认情况下非HTTPS的网络访问是禁止的并且不能再通过简单粗暴的向Info.plist中添加NSAllowsArbitraryLoads 设置绕过ATS(App Transport Security)的限制(否则须在应用审核时进行说明并很可能会被拒)。所以还未进行相应配置的公司需要尽快将升级为HTTPS的事项提上进程了。本文将简述HTTPS及配置数字证书的原理并以配置实例和出现的问题进行说明,希望能对你提供帮助。(比心~)
HTTPS: 简单来说,HTTPS就是HTTP协议上再加一层加密处理的SSL协议,即HTTP安全版。相比HTTP,HTTPS可以保证内容在传输过程中不会被第三方查看、及时发现被第三方篡改的传输内容、防止身份冒充,从而更有效的保证网络数据的安全。 HTTPS客户端与服务器交互过程: 1、 客户端第一次请求时,服务器会返回一个包含公钥的数字证书给客户端; 2、 客户端生成对称加密密钥并用其得到的公钥对其加密后返回给服务器; 3、 服务器使用自己私钥对收到的加密数据解密,得到对称加密密钥并保存; 4、 然后双方通过对称加密的数据进行传输。
数字证书: 在HTTPS客户端与服务器第一次交互时,服务端返回给客户端的数字证书是让客户端验证这个数字证书是不是服务端的,证书所有者是不是该服务器,确保数据由正确的服务端发来,没有被第三方篡改。数字证书可以保证数字证书里的公钥确实是这个证书的所有者(Subject)的,或者证书可以用来确认对方身份。证书由公钥、证书主题(Subject)、数字签名(digital signature)等内容组成。其中数字签名就是证书的防伪标签,目前使用最广泛的SHA-RSA加密。 证书一般分为两种:
1.一种是向权威认证机构购买的证书,服务端使用该种证书时,因为苹果系统内置了其受信任的签名根证书,所以客户端不需额外的配置。为了证书安全,在证书发布机构公布证书时,证书的指纹算法都会加密后再和证书放到一起公布以防止他人伪造数字证书。而证书机构使用自己的私钥对其指纹算法加密,可以用内置在操作系统里的机构签名根证书来解密,以此保证证书的安全。
2.另一种是自己制作的证书,即自签名证书。好处是不需要花钱购2买,但使用这种证书是不会受信任的,所以需要我们在代码中将该证书配置为信任证书.
自签名证书具体实现: 我们在使用自签名证书来实现HTTPS请求时,因为不像机构颁发的证书一样其签名根证书在系统中已经内置了,所以我们需要在App中内置自己服务器的签名根证书来验证数字证书。首先将服务端生成的.cer格式的根证书添加到项目中,注意在添加证书要一定要记得勾选要添加的targets。这里有个地方要注意:苹果的ATS要求服务端必须支持TLS 1.2或以上版本;必须使用支持前向保密的密码;证书必须使用SHA-256或者更好的签名hash算法来签名,如果证书无效,则会导致连接失败。由于我在生成的根证书时签名hash算法低于其要求,在配置完请求时一直报_NSURLErrorServerCertificateUntrusted_ = -1202错误,希望大家可以注意到这一点。
那么如何在Moya中使用自签名的证书来实现HTTPS网络请求呢,请期待下回我专门分享…需要自定义一个Manager管理
综合使用的方法如下
定义一个公用的Moya请求服务对象
let MyAPIProvider = MoyaProvider<NetAPIManager>(endpointClosure: myEndpointClosure,requestClosure: requestClosure, plugins: [NetworkLoggerPlugin(verbose: true, responseDataFormatter: JSONResponseDataFormatter),myNetworkPlugin])// MARK: -创建一个Moya请求
func sendRequest(_ postDict: Dictionary<String, Any>? = nil, success:@escaping (Dictionary<String, Any>)->(), failure:@escaping (MoyaError)->()) -> Cancellable? { let request = MyAPIProvider.request(.Show) { result inswitch result {case let .success(moyaResponse):do {let any = try moyaResponse.mapJSON()let data =moyaResponse.datalet statusCode =moyaResponse.statusCodeMyLog("\(data) --- \(statusCode) ----- \(any)")success(["":""])} catch {} case let .failure(error):print(error)failure(error)}}return request
}
取消所有的Moya请求
// MARK: -取消所有请求
func cancelAllRequest() {
//MyAPIProvider.manager.session.invalidateAndCancel()//取消所有请求MyAPIProvider.manager.session.getTasksWithCompletionHandler { dataTasks, uploadTasks, downloadTasks indataTasks.forEach { $0.cancel() }uploadTasks.forEach { $0.cancel() }downloadTasks.forEach { $0.cancel() }}//let sessionManager = Alamofire.SessionManager.default//sessionManager.session.getTasksWithCompletionHandler { dataTasks, uploadTasks, downloadTasks in//dataTasks.forEach { $0.cancel() }//uploadTasks.forEach { $0.cancel() }//downloadTasks.forEach { $0.cancel() }//}}
iOS 使用Moya网络请求相关推荐
- iOS 项目中 网络请求Alamofire 的二次封装
iOS 项目中 网络请求Alamofire 的二次封装 1.先创建 网络请求的工具类 NetWorkTool 继承自NSObject class NetWorkTool: NSObject {} 2. ...
- ios开发循环网络请求_iOS开发--HTTP的网络请求状态代码详解
网络请求是iOS项目的一个大部分,而且大部分的iOS的项目的网络请求是根据AFN进行的二次封装,我们查看返回的结果或者error的网络错误code,从而确认错误类型,针对行的进行调试修改. 说明:一下 ...
- iOS 中的网络请求 (同步请求、异步请求、GET请求、POST请求)
1.同步请求可以从因特网请求数据,一旦发送同步请求,程序将停止用户交互,直至服务器返回数据完成,才可以进行下一步操作, 2.异步请求不会阻塞主线程,而会建立一个新的线程来操作,用户发出异步请求后,依然 ...
- ios在异步网络请求上实现同步逻辑
2019独角兽企业重金招聘Python工程师标准>>> 前提: 可能遇到一些问题,比如上传多个数据,需要等多个数据上传成功后做一定的处理,而且一个个上传,万一哪个上传失败了,后面就不 ...
- ios开发循环网络请求_谈谈 iOS 网络层设计(SSJNetWork封装缓冲,log日志,自动取消网络请求)...
2.delegate效率高,delegate只是保存了一个对象指针3.在多个通信事件的时候,delegate显得直观也易维护. delegate缺点:1.因方法的声明和实现分离开来,代码的连贯性不是很 ...
- ios开发循环网络请求_如何简化网络请求接口开发
日常开发中,需要大量和后端对接接口,很容易写出大量的模板代码,比如把对接口的请求放到组件内,或者虽然有数据访问层,但是有大量 get,post 方法的调用,传参的字符串拼接,异常处理等等,有些逻辑是可 ...
- iOS 设计中 网络请求之 同步请求(json 请求--新方法和老方法)
//老的网络请求的方法- --NSData *data= [NSURLConnection sendSynchronousRequest:URlrequest returningResponse:&a ...
- ios开发循环网络请求_GitHub - JadenTeng/ResourceX: iOS网络请求,网络泛型编程,工具类的封装,基于AFNetworking 实现, NSCache数据缓存...
ResourceX 通过AFNetworking.YYModel 解析网络泛型编程简化网络请求 现如今,网络通信几乎涉及每一个app程序.对于绝大多数请求HTTP API的方法,它们的执行流程都可以分 ...
- iOS客户端校验https网络请求证书
其实iOS系统的网络请求都有校验,比如NSURLConnection.NSURLSession都有系统的自动校验.具体的校验可进行百度 我使用的是NSURLConnection进行的网络请求,NSUR ...
最新文章
- mysql日常有哪些用_mysql日常笔记(持续更新)
- 005_控制器和动作
- 你不知道的Node.js性能优化,读了之后水平直线上升
- vue项目统一响应_vue中使用$set实现深入响应式原理
- python fsolve说明_Python fsolve()抱怨形状.为什么?
- jsp通过include指令引入html乱码的解决方法
- mysql not like 没用_PHP - 使用NOT LIKE时,mysql查询不起作用
- 【报告分享】2020中国248家独角兽报告.pdf(附下载链接)
- “Get that job at Google”笔记
- Toontrack Superior Drummer for Mac(鼓音乐制作工具)
- 分布式机器学习\分布式KMeans
- Python 面向对象 (六) 实例学员管理系统
- 图像算法工程师的一般要求
- wincc7.4安装授权 全(文件分享)
- App Inventor 模拟器问题的解决
- JavaFX官方文档
- PB 打印机打印横纵向设置
- 关于网站漏洞的案例和解决思路
- 招标系统html模板信息,招投标信息管理系统.docx
- C语言实现BP神经网络并检测手写数字
热门文章
- gnocchi-采样数据存储流程分析(002)--数据的异步统计
- 怎样清理苹果电脑磁盘空间_Macbook苹果电脑提示磁盘空间不足怎么办【解决方法】...
- 计算机毕业设计ssm财务报账管理系统l6tbn系统+程序+源码+lw+远程部署
- C语言画贝塞尔曲线的函数
- 爱贝支付 - 服务端 - nodejs实现
- 虚拟机Linux安装与应用(保姆级)
- Paddle入门实战系列(一):车牌检测与识别
- a股行情接口功能特点
- app版本更新 下载apk后没有跳转到安装页面
- 只有我一个人对ChatGPT感到蕉绿吗?