美文网首页iOS
【iOS开发】NSURLProtocol的使用

【iOS开发】NSURLProtocol的使用

作者: xiacheng | 来源:发表于2016-12-28 16:07 被阅读333次

    参考文章:
    iOS开发之--- NSURLProtocol
    NSURLProtocol

    NSURLProtocol 是一个抽象类,它是一个抽象类,你可以通过子类化来定义新的或已经存在的URL加载行为。
    利用这个类,可以用来实现:

    1. 通过让网页来请求自定义的特定的url,来实现H5与原生应用的交互
    2. 对发出请求的header进行格式化
    3. 创建本地代理服务,用于数据变化时对URL请求进行更改
      ...

    如何使用
    1、注册你的NSURLProtocol 子类
    当请求被加载时,系统会向每一个注册过的protocol询问:“Hey你能控制这个请求吗?”第一个通过 +canInitWithRequest: 回答为 YES 的protocol就会控制该请求。URL protocol会被以注册顺序的反序访问,所以当在-application:didFinishLoadingWithOptions:方法中调用 [NSURLProtocol registerClass:[MyURLProtocol class]];时,你自己写的protocol比其他内建的protocol拥有更高的优先级。

    2、实现+canInitWithRequest: 方法
    这个方法主要是说明你是否打算处理这个request,如果是返回yes,否则返回NO。
    tips: 因为我们处理时的思路一般先拦截请求,然后对请求进行一定的修改或处理,然后利用NSURLSesson或者NSURLConnection来真正的发送请求。这时就没必要再对其进行处理,不然会造成死循环。所以,要有一个标示来标示这个request是否已经被我们处理过了。一般使用的方法是在- (void)startLoading方法里用
    [NSURLProtocol setProperty:@YES forKey:URLProtocolHandledKey inRequest:mutableReqeust];方法来为这个request加一个property,在+canInitWithRequest:`方法里判断有没有这个property。
    如下:

    + (BOOL)canInitWithRequest:(NSURLRequest *)request
    {
        //只处理host里面包含@“baidu”的请求
        NSString *urlStr = [request URL].host;
        if ([urlStr containsString:@"www.google.com"]) {
            if ([NSURLProtocol propertyForKey:URLProtocolHandledKey inRequest:request]) {
                return NO;
            }
            return YES;
        }
        return NO;
    }
    

    3、实现 +canonicalRequestForRequest
    这个方法返回一个请求,即是我们修改过的请求。

    + (NSURLRequest *) canonicalRequestForRequest:(NSURLRequest *)request {
        NSMutableURLRequest *mutableReqeust = [request mutableCopy];
        mutableReqeust = [self redirectHostInRequset:mutableReqeust];
        return mutableReqeust;
    }
    +(NSMutableURLRequest*)redirectHostInRequset:(NSMutableURLRequest*)request
    {
        if ([request.URL host].length == 0) {
            return request;
        }
        
        NSString *originUrlString = [request.URL absoluteString];
        NSString *originHostString = [request.URL host];
        NSRange hostRange = [originUrlString rangeOfString:originHostString];
        if (hostRange.location == NSNotFound) {
            return request;
        }
        //定向到百度搜索
        NSString *ip = @"www.baidu.com";
        NSString *urlString = [originUrlString stringByReplacingCharactersInRange:hostRange withString:ip];
        NSURL *url = [NSURL URLWithString:urlString];
        request.URL = url;
        return request;
    }
    

    4、实现开始、停止请求方法

    - (void)startLoading
    {
        NSMutableURLRequest *mutableReqeust = [[self request] mutableCopy];
        //标示改request已经处理过了,防止无限循环
        [NSURLProtocol setProperty:@YES forKey:URLProtocolHandledKey inRequest:mutableReqeust];
        self.connection = [NSURLConnection connectionWithRequest:mutableReqeust delegate:self];
    }
    //停止请求
    - (void)stopLoading
    {
        [self.connection cancel];
    }
    

    5、将请求的结果通过client返回给URL Loading System
    因为这里我作的是NSURLConnect来做的请求,所以在NSURLConnectDataDelegate 方法里面来做这件事,如果你是你的NSURLSession,方法类似。

    - (nullable NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(nullable NSURLResponse *)response
    {
        return request;
    }
    - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
    {
        [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageAllowed];
    }
    - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
    {
        [self.client URLProtocol:self didLoadData:data];
    }
    - (void)connectionDidFinishLoading:(NSURLConnection *)connection
    {
        [self.client URLProtocolDidFinishLoading:self];
    }
    - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
    {
        [self.client URLProtocol:self didFailWithError:error];
    }
    

    一个简单的Demo
    上面即是NSURLProtocol 使用的介绍。
    ps:在研究这个问题的时候,看到好多地方提到URL Loading System,现在网络请求只是会用,具体的实现还不是很懂,后面要找时间研究一下。

    相关文章

      网友评论

        本文标题:【iOS开发】NSURLProtocol的使用

        本文链接:https://www.haomeiwen.com/subject/gmmyvttx.html