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内容加载进度.是否加载完成 如何处理去 ...
随机推荐
- 如何更改Audition的界面颜色
如何更改Audition的界面颜色_百度经验 https://jingyan.baidu.com/article/77b8dc7fce2c6a6174eab6f6.html
- 魔力Python--if __name__ == '__main__' 的理解
if __name__ == '__main__' 的理解 __name__ 是当前模块名,当模块被直接运行时模块名为 __main__ . 这句话的意思就是,当模块被直接运行时,以下代码块将被运行, ...
- Django Cookie和Seesion
1.cookie不属于http协议范围,由于http协议无法保持状态,但实际情况,我们却又需要“保持状态”,因此cookie就是在这样一个场景下诞生.cookie的工作原理是:由服务器产生内容,浏览器 ...
- Jdbc使用SSH连接mysql
pom.xml <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-ja ...
- centos病毒
#!/bin/bash exec &>/dev/null {echo,ZXhlYyAmPi9kZXYvbnVsbApleHBvcnQgUEFUSD0kUEFUSDovYmluOi9zYm ...
- centos7.4下的KVM虚拟机安装使用
本来是用的vmware,不过后来想试下KVM,想着装个ZSTACK也行,结果zstack使用网络安装没搞明白,把物理机系统毁了,这下彻底完蛋了,只好还装个centos了,但是又不想用VMWARE就想起 ...
- 转: Ext.data.Store 修改Post请求
Extjs 4.0版本 var Store = Ext.create('Ext.data.Store', { pageSize: pageSize, model: 'Ext.data.Model名称' ...
- celery (二) task调用
调用 TASK 基础 task 的调用方式有三种: 类似普通函数的调用方式, 通过 __calling__ 调用 ,类似 function() 通过 apply_async() 调用,能接受较多的参数 ...
- SVM-sklearn
目的:1000张数字0-9的手写数字,训练识别手写数字:将其作为32*32的0,1化的数字,随后会将其变为1024列的一个向量 原理:SVM就是把平面的点变为一个空间的点,更好切,核函数就是怎么把他变 ...
- OGRE
[编译 OGRE C#] 1.官网下载 OGRE 源码. 2.打开CMake,指定好OGRE目录,以及生成目标目录. 3.将 CMake/Modules 目录下的 FindSwig.cmake 中的 ...