重定向定义:重定向(Redirect)就是通过各种方法将各种网络请求重新定个方向转到其它位置(如:网页重定向、域名的重定向、路由选择的变化也是对数据报文经由路径的一种重定向)。

  NSURLProtocol:NSURLProtocol能够让你去重新定义苹果的URL加载系统 (URL Loading System)的行为,URL Loading System里有许多类用于处理URL请求,比如NSURL,NSURLRequest,NSURLConnection和NSURLSession等,当URL Loading System使用NSURLRequest去获取资源的时候,它会创建一个NSURLProtocol子类的实例,你不应该直接实例化一个NSURLProtocol,NSURLProtocol看起来像是一个协议,但其实这是一个类,而且必须使用该类的子类,并且需要被注册。
    NSURLProtocol使用场景

不管你是通过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)的更多相关文章

  1. iOS 代理 重定向消息 forwardInvocation

    今天简单研究一下iOS的重定向消息forwardInvocation: 首先看看Invocation类: @interface NSInvocation : NSObject { @private _ ...

  2. 关于ios越狱开发的那些事

    也许吧,每每接触某些新东西的时候,都有点犯晕吧,这不是应该要的. 第一次接触ios越狱开发,也是这样吧.这篇主要是从无到有的说一下ios越狱的开发,网上很多的教程大部门都比较旧了吧,放在新设备上总是出 ...

  3. [转载] iOS开发分辨率那点事

    1 iOS设备的分辨率 iOS设备,目前最主要的有3种(Apple TV等不在此讨论),按分辨率分为两类 iPhone/iPod Touch 普屏分辨率    320像素 x 480像素 Retina ...

  4. iOS编程中throttle那些事

    不知道大家对throttle这个单词是否看着眼熟,还是说对这个计算机基础概念有很清晰的了解了.今天就来聊聊和throttle相关的一些技术场景. 定义 我经常有一种感觉,对于英语这门语言的语感,会影响 ...

  5. iOS开发——设计模式那点事

    单例模式(Singleton) 概念:整个应用或系统只能有该类的一个实例 在iOS开发我们经常碰到只需要某类一个实例的情况,最常见的莫过于对硬件参数的访问类,比如UIAccelerometer.这个类 ...

  6. iOS UIWebView重定向Cookie

    // 1. 取出当前的cookies NSArray<NSHTTPCookie *> *cookies = [NSHTTPCookieStorage sharedHTTPCookieSto ...

  7. ios WKWebView 与 JS 交互实战技巧

    一.WKWebView 由于Xcode8发布之后,编译器开始不支持iOS 7了,这样我们的app也改为最低支持iOS 8.0,既然需要与web交互,那自然也就选择使用了 iOS 8.0之后 才推出的新 ...

  8. iOS App开发那些事:如何选择合适的人、规范和框架?

    http://www.cocoachina.com/ios/20141202/10386.html 自从做Team Leader之后,身上权责发生了变化,于是让我烦恼的不再是具体某个功能,某个界面的实 ...

  9. WKWebView与Js (OC版)

    OC如何给JS注入对象及JS如何给IOS发送数据 JS调用alert.confirm.prompt时,不采用JS原生提示,而是使用iOS原生来实现 如何监听web内容加载进度.是否加载完成 如何处理去 ...

随机推荐

  1. cached_property的使用

    cached_property修饰过的函数,变成是对象的属性,该对象第一次引用该属性时,会调用函数,对象第二次引用该属性时就直接从词典中取了,这也说明引用属性是经过__getattritue__. c ...

  2. Django2.X报错-------ModuleNotFoundError: No module named 'django.core.urlresolvers'

    django2.0 把原来的 django.core.urlresolvers 包 更改为了 django.urls包.所以将导入的包修改为django.urls.

  3. 为什么移动构造要使用noexcept

    vector::push_back操作,保证了如果过程中出现异常,vector不会发生变化. push_back过程中,可能会因为已有内存空间不够,申请新的内存,同时把原内存中已有的元素,放到新申请的 ...

  4. 回溯法 17. Letter Combinations of a Phone Number

    class Solution { public: map<char,string> dict; vector<string> letterCombinations(string ...

  5. User authentication in Django(用户认证)

    一,概述: auth 系统包括: 1)Users 2)Permissions: Binary (yes/no) flags designating whether a user may perform ...

  6. redis 配置文件解释 以及集群部署

    redis是一款开源的.高性能的键-值存储(key-value store),和memcached类似,redis常被称作是一款key-value内存存储系统或者内存数据库,同时由于它支持丰富的数据结 ...

  7. CSS 背景图像 背景图片定位

    背景图片定位 background-position属性可以给背景图片定位. background-position属性有两个值,第一个值是水平位置,第二个值是垂直位置.这两个值可以使用百分比来表示( ...

  8. 循环输入到列表的基础方法 -----python-----

    print('向列表中添加元素(输入“#”结束)\n并查看添加完的列表') list1=[] while 1: username=input('>>>') if (username. ...

  9. Harbor私有镜像仓库(上)

    上图配置为工作环境 特别注意:win10现在不允许使用私有ca证书,到时登录浏览器会失败,可以选用火狐浏览器. 创建自己的CA证书 openssl req -newkey rsa:4096 -node ...

  10. ABAP 程序/接口调用其他程序的数据

    在ABAP遇到的业务场景中,可能会遇到一种情况,需要调用其他报表的数据来发送或者二次加工,这个时候又不想对源程序做大的改动.有以下几种思路解决. 1.修改源程序,将需要展示的数据存储到DB中,然后主程 ...