iOS 关于重定向的那些事(NSURLProcotol-WKWebView)
重定向定义:重定向(Redirect)就是通过各种方法将各种网络请求重新定个方向转到其它位置(如:网页重定向、域名的重定向、路由选择的变化也是对数据报文经由路径的一种重定向)。
不管你是通过UIWebView, NSURLConnection 或者第三方库 (AFNetworking, MKNetworkKit等),他们都是基于NSURLConnection或者 NSURLSession实现的,因此你可以通过NSURLProtocol做自定义的操作。
- 重定向网络请求
- 忽略网络请求,使用本地缓存
- 自定义网络请求的返回结果
- 一些全局的网络请求设置
由于公司做免流增值业务,所以对于重定向的使用比较多,当用户通过手机流量访问部分请求时,需要进行重定向,让用户走免流服务器,这样可以做到定向流量的需求。
言归正传,关于NSURLProcotol的基本使用可以参考这篇文章:http://www.jianshu.com/p/7c89b8c5482a
如果要是对于WKWebView的配置需要特别注意一下。
注意点:
- WKWebView 在独立于 App Process 进程之外的 Network Process 进程中执行网络请求,请求数据不经过主进程,因此,在 WKWebView 上直接使用 NSURLProtocol 无法拦截请求。
- 可见内部对全局的 WebProcessPool 进行了自定义 scheme 的注册和注销。
- WKBrowsingContextController 通过 registerSchemeForCustomProtocol 向 WebProcessPool 注册全局自定义 scheme
- WebProcessPool 使用已注册的 scheme 初始化 Network Process 进程配置,同时设置 CustomProtocolManager,负责把网络请求通过 IPC 发送到 App Process 进程、也接收从 App Process 进程返回的网络响应 response
- CustomProtocolManager 注册了 NSURLProtocol 的子类 WKCustomProtocol,负责拦截网络请求处理
- CustomProtocolManagerProxy 中的 WKCustomProtocolLoader 使用 NSURLConnection 发送实际的网络请求,并将响应 response 返回给 CustomProtocolManager
使用示例:对图片的处理
+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
NSString* extension = request.URL.pathExtension;
BOOL isImage = [@[@"png", @"jpeg", @"gif", @"jpg"] indexOfObjectPassingTest:^BOOL(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
return [extension compare:obj options:NSCaseInsensitiveSearch] == NSOrderedSame;
}] != NSNotFound;
return [NSURLProtocol propertyForKey:FilteredKey inRequest:request] == nil && isImage;
}
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
return request;
}
- (void)startLoading {
NSMutableURLRequest* request = self.request.mutableCopy;
[NSURLProtocol setProperty:@YES forKey:FilteredKey inRequest:request];
NSData* data = UIImagePNGRepresentation([UIImage imageNamed:@"image"]);
NSURLResponse* response = [[NSURLResponse alloc] initWithURL:self.request.URL MIMEType:@"image/png" expectedContentLength:data.length textEncodingName:nil];
[self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageAllowed];
[self.client URLProtocol:self didLoadData:data];
[self.client URLProtocolDidFinishLoading:self];
}
重点:
进行注册和注销
//注册
+ (void)wk_registerScheme:(NSString*)scheme; //注销
+ (void)wk_unregisterScheme:(NSString*)scheme;
实现注册与注销:
FOUNDATION_STATIC_INLINE Class ContextControllerClass() {
static Class cls;
if (!cls) {
cls = [[[WKWebView new] valueForKey:@"browsingContextController"] class];
}
return cls;
}
FOUNDATION_STATIC_INLINE SEL RegisterSchemeSelector() {
return NSSelectorFromString(@"registerSchemeForCustomProtocol:");
}
FOUNDATION_STATIC_INLINE SEL UnregisterSchemeSelector() {
return NSSelectorFromString(@"unregisterSchemeForCustomProtocol:");
}
@implementation NSURLProtocol (WebKitSupport)
+ (void)wk_registerScheme:(NSString *)scheme {
Class cls = ContextControllerClass();
SEL sel = RegisterSchemeSelector();
if ([(id)cls respondsToSelector:sel]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[(id)cls performSelector:sel withObject:scheme];
#pragma clang diagnostic pop
}
}
+ (void)wk_unregisterScheme:(NSString *)scheme {
Class cls = ContextControllerClass();
SEL sel = UnregisterSchemeSelector();
if ([(id)cls respondsToSelector:sel]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[(id)cls performSelector:sel withObject:scheme];
#pragma clang diagnostic pop
}
}
注册内容基本已经完成,完成之后需要将在全局中注册 [NSURLProtocol registerClass:[ReplacingImageURLProtocol class]];
这样就完成了对于WKWebViewde拦截与重定向,可以通过WKNavigationDelegate的代理来获取结果:
#pragma mark - WKNavigationDelegate
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
[webView evaluateJavaScript:@"document.title" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
if ([result isKindOfClass:[NSString class]]) {
self.title = result;
}
}];
}
#pragma mark - UIWebViewDelegate
- (void)webViewDidFinishLoad:(UIWebView *)webView {
self.title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
}
#pragma mark - Getters
- (UIView *)webView {
if (!_webView) {
_webView = [[WKWebView alloc] initWithFrame:self.view.bounds];
_webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
if ([_webView respondsToSelector:@selector(setNavigationDelegate:)]) {
[_webView setNavigationDelegate:self];
}
if ([_webView respondsToSelector:@selector(setDelegate:)]) {
[_webView setDelegate:self];
}
}
return _webView;
}
以上的就是对于WKWebView的处理了,对于NSURLProcotol的使用基本上就是这些,使用它可以让你在不改变链接的情况下进行重定向,也方便全局代理的使用与处理,可以极大的提高效率。有什么疑问的可以加我的扣扣:1123231279,大家可以一起探讨。
iOS 关于重定向的那些事(NSURLProcotol-WKWebView)的更多相关文章
- iOS 代理 重定向消息 forwardInvocation
今天简单研究一下iOS的重定向消息forwardInvocation: 首先看看Invocation类: @interface NSInvocation : NSObject { @private _ ...
- 关于ios越狱开发的那些事
也许吧,每每接触某些新东西的时候,都有点犯晕吧,这不是应该要的. 第一次接触ios越狱开发,也是这样吧.这篇主要是从无到有的说一下ios越狱的开发,网上很多的教程大部门都比较旧了吧,放在新设备上总是出 ...
- [转载] iOS开发分辨率那点事
1 iOS设备的分辨率 iOS设备,目前最主要的有3种(Apple TV等不在此讨论),按分辨率分为两类 iPhone/iPod Touch 普屏分辨率 320像素 x 480像素 Retina ...
- iOS编程中throttle那些事
不知道大家对throttle这个单词是否看着眼熟,还是说对这个计算机基础概念有很清晰的了解了.今天就来聊聊和throttle相关的一些技术场景. 定义 我经常有一种感觉,对于英语这门语言的语感,会影响 ...
- iOS开发——设计模式那点事
单例模式(Singleton) 概念:整个应用或系统只能有该类的一个实例 在iOS开发我们经常碰到只需要某类一个实例的情况,最常见的莫过于对硬件参数的访问类,比如UIAccelerometer.这个类 ...
- iOS UIWebView重定向Cookie
// 1. 取出当前的cookies NSArray<NSHTTPCookie *> *cookies = [NSHTTPCookieStorage sharedHTTPCookieSto ...
- ios WKWebView 与 JS 交互实战技巧
一.WKWebView 由于Xcode8发布之后,编译器开始不支持iOS 7了,这样我们的app也改为最低支持iOS 8.0,既然需要与web交互,那自然也就选择使用了 iOS 8.0之后 才推出的新 ...
- iOS App开发那些事:如何选择合适的人、规范和框架?
http://www.cocoachina.com/ios/20141202/10386.html 自从做Team Leader之后,身上权责发生了变化,于是让我烦恼的不再是具体某个功能,某个界面的实 ...
- WKWebView与Js (OC版)
OC如何给JS注入对象及JS如何给IOS发送数据 JS调用alert.confirm.prompt时,不采用JS原生提示,而是使用iOS原生来实现 如何监听web内容加载进度.是否加载完成 如何处理去 ...
随机推荐
- asp.net 微信开发(一)
在准备工作中,我们已经完成准备工作,接下来就是进行开发啦,应该怎么来开发呢??容我想想...我觉得我们可以直接让用户的消息发送到微信的消息,转到我们自己的服务器上面!!感觉好厉害的样子 1.首先写 验 ...
- Jmeter学习记录
JSON正则表达式提取规则 https://www.cnblogs.com/hc1020/p/7723720.html Jmeter非GUI下执行日志 执行命令 ./jmeter -n -t $ ...
- swift-UIPickerView(选择控件)
import UIKit //UIPickerView 的委托协议是 UIPickerViewDelegate,数据源是 UIPickerViewDataSource.我们需要在视图控制器中声明实现 ...
- 2018-2019-2 网络对抗技术 20165304 Exp2 后门原理与实践
后门的基本概念及实验内容 常用后门工具 netcat Win获得Linux Shell Linux获得Win Shell Meterpreter 实验内容 任务一:使用netcat获取主机操作Shel ...
- vmware 进入虚拟机VMware的系统后鼠标不能点
vmware 进入虚拟机VMware的系统后鼠标不能点 1)关闭虚拟机,重启win10,再打开虚拟机好了 2)
- Https的前世今生
1.年前会议 马上要过年了,公司业务上的需求也少了很多,这不,王小二他们召开了一场技术会议,盘点年前能干点啥. 只见C哥写了一份清单,其中一项是全站升级https. C哥说:https是一种趋势,但目 ...
- 云栖大会day2 下午
下午内容普遍比较水 参与了intel的宣讲会,都能把人听睡着了 又回来听了开发者宣讲会 讲了人的成才选择,造势之人 顺势之人 逐流之人 我认为,跟人的能力关联不大,跟眼界关联很大, flink 参与到 ...
- linux下redis的安装方法
一.Linux环境下安装Redis Redis的官方下载网址是:http://redis.io/download (这里下载的是Linux版的Redis源码包) Redis服务器端的默认端口是6 ...
- Traceback (most recent call last): File "c:\program files (x86)\microsoft visual studio\2019\community\common7\ide\extensions\microsoft\python\core\Packages\ptvsd\_vendored\pydevd\_pydevd_bundle\pyd
某次编码,debug的时候突然突然突然给我报这个错: Traceback (most recent call last): File "c:\program files (x86)\mi ...
- 实现对Java配置文件Properties的读取、写入与更新操作
/** * 实现对Java配置文件Properties的读取.写入与更新操作 */ package test; import java.io.BufferedInputStream; import j ...