[iOS] NSURLProtocol 拦截器

本文详细介绍了如何利用NSURLProtocol实现网络拦截和Mock数据。通过创建自定义子类并注册,可以拦截URL请求,进行参数修改或返回Mock数据。文中提供了示例代码,并分享了一个开源项目HTTPInterceptor,支持Objective-C和Swift,方便集成和使用。
摘要由CSDN通过智能技术生成

在这里插入图片描述

为了这篇文章的内容,写了一个小项目,支持ObjectiveC,Swift语言。
支持Cocoapods集成,主要功能是,网络拦截和Mock数据。 有兴趣的同学可以看看。

项目地址: https://github.com/zColdWater/HTTPInterceptor

一,NSURLProtocol 的介绍

Apple 官方文档 https://developer.apple.com/documentation/foundation/urlprotocol

NSURLProtocol 是一个抽象类,你不能直接创建这个实例,如果你想使用它的功能,你应该继承它创建属于自己的子类,然后重写 NSURLProtocol 的方法。

1.关于NSURLProtocol类定义

我们看下这个类的定义:

open class URLProtocol : NSObject {
    public init(request: URLRequest, cachedResponse: CachedURLResponse?, client: URLProtocolClient?)
    // 操作被拦截协议的对象,用于给予被拦截者回调。
    open var client: URLProtocolClient? { get }
    // 拦截到的request
    open var request: URLRequest { get }
    // 给接收者一个缓存对象
    @NSCopying open var cachedResponse: CachedURLResponse? { get }
    // 通过URLRequest参数返回是否要拦截这个Request
    open class func canInit(with request: URLRequest) -> Bool
    // 是不是要重新返回一个新的request,一般你可以在原request基础上,加一些参数等,然后再返回,返回后,request属性就是你返回的request了。
    open class func canonicalRequest(for request: URLRequest) -> URLRequest
    // 比较两个URLRequest的缓存是否相当,如果相当,返回true,否则返回false。 目前还没想到有什么场景需要重写这个方法。
    open class func requestIsCacheEquivalent(_ a: URLRequest, to b: URLRequest) -> Bool
    // 开始你需求的操作了,可以通过self.request拿到拦截的request。
    open func startLoading()
    // 取消任务后,你要的动作。 
    open func stopLoading()
    // 读取URLRequest的附加属性,通过Key
    open class func property(forKey key: String, in request: URLRequest) -> Any?
    // 设置URLRequest的附加属性,通过Key
    open class func setProperty(_ value: Any, forKey key: String, in request: NSMutableURLRequest)
    // 移除URLRequest的附加属性,通过Key
    open class func removeProperty(forKey key: String, in request: NSMutableURLRequest)
    // 将当前协议注册进拦截系统
    open class func registerClass(_ protocolClass: AnyClass) -> Bool
    // 取消注册 和 registerClass 动作相反
    open class func unregisterClass(_ protocolClass: AnyClass)
}

extension URLProtocol {
    @available(iOS 8.0, *)
    // 是否要拦截这个URLSessionTask,它和 canInit(with request: URLRequest) 只能有一个被调用,如果声明了  canInit(with task: URLSessionTask) 就不会走 canInit(with request: URLRequest) 了。
    open class func canInit(with task: URLSessionTask) -> Bool
    @available(iOS 8.0, *)
    public convenience init(task: URLSessionTask, cachedResponse: CachedURLResponse?, client: URLProtocolClient?)
    @available(iOS 8.0, *)
    // 获取拦截的task
    @NSCopying open var task: URLSessionTask? { get }
}

2.如何拦截呢,示例代码?

那么我们一般怎么用它来拦截URL呢? 我写了一个示例代码,MyURLProtocol在页面最开始先注册好。 然后你可以创建任何已经有的标准协议URL还是你自定义的协议URL,都可以。 然后通过URLSession创建一个会话,再用这个会话loading你的URL,开始这个task。 MyURLProtocol 就能够拦截到你的URL了,下面的例子。

例子输出:

拦截的RequestURL字符串:myscheme://www.appcoda.com/working-url-schemes-ios/
拦截的RequestURL字符串:http://www.appcoda.com/working-url-schemes-ios/
拦截的RequestURL字符串:https://www.appcoda.com/working-url-schemes-ios/
拦截的RequestURL字符串:file:///a/working-url-schemes-ios/
拦截的RequestURL字符串:https://www.appcoda.com/working-url-schemes-ios/

例子代码:

import UIKit

class ViewController: UIViewController {
   
    
    override func viewDidLoad() {
   
        super.viewDidLoad()
        URLProtocol.registerClass(MyURLProtocol.self)
        
        // 自定义协议的URL
        let customUrl = URL(string
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值