Javascript如何传递大数据传给Objective-C

Javascript与UIWebView交互,通常的做法是双方约定一个协议,如:protocol://function/params,在Javascript中用window.location.href = "protocol://function/params";来请求,然后UIWebview的delegate方法:- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType会拦截到这个请求,分析出所要进行的操作。但是通过window.location.href这种方式实际上是GET的方式(请不要计较说GET和POST是http://才有的请求方式- -),传输的数据量是有一定限制的。当数据量很大时,假如达到了5M,是不是可以用POST方式呢,我们知道POST是没有限制的。


在Foundation的URL加载系统中有一个NSURLProtocol类,它是一个抽象类,可以通过子类化来定义新的或已存在的url加载行为。当它的子类注册到url加载系统中时,便可拦截所有url请求。是你想要的请求你可以对其处理,不是的话就不管,交给系统中其他的NSURLProtocol子类处理。那么js发出的这个post请求,自然可以被你拦截到啦,你要传的大数据就在request的body里啦,哈哈~。注意!以post的方式请求,url的scheme必须是http://,可不能是那个什么protocol://啦。


那么问题的关键就是这个NSURLProtocol的子类究竟怎么实现了,创建一个AppProtocolHandler类继承NSURLProtocol,具体的实现如下:

AppProtocolHandler.m

#import "AppProtocolHandler.h"
static NSString * const MyURLProtocolHandledKey = @"MyURLProtocolHandledKey";
@interface AppProtocolHandler()
@property (nonatomic, strong) NSURLConnection *connection;
@property (nonatomic, strong) NSMutableData *mutableData;
@property (nonatomic, strong) NSURLResponse *response;
@end
@implementation AppProtocolHandler

//注册自己的urlprotocl到url加载系统中
+ (void)registerSpecialProtocol {
    static BOOL inited = NO;
    
    if (!inited) {
        inited = YES;
        [NSURLProtocol registerClass:[AppProtocolHandler class]];
    }
}

- (void)handelRequest
{
    id<NSURLProtocolClient> client = [self client];
    NSURLRequest *request = [self request];
    NSURL *url = [request URL];
    //我们想要的数据
    NSData *bodyData = [request HTTPBody];
    NSString* bodyStr = [[NSString alloc] initWithData:bodyData encoding:NSUTF8StringEncoding];
    NSLog(@"[request HTTPBody]: %@", bodyStr);
    
    //响应一个空的data回去
    NSData *data = [NSData data];
    NSURLCacheStoragePolicy caching = NSURLCacheStorageNotAllowed;
    NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:url MIMEType:@"text/plain" expectedContentLength:[data length] textEncodingName:@"utf-8"];
    [client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:caching];
    [client URLProtocol:self didLoadData:data];
    [client URLProtocolDidFinishLoading:self];
}

#pragma mark - Override NSURLProtocol Methods

+ (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b
{
    return [super requestIsCacheEquivalent:a toRequest:b];
}

+ (BOOL)canInitWithRequest:(NSURLRequest *)request
{
    if ([NSURLProtocol propertyForKey:MyURLProtocolHandledKey inRequest:request]) {
        return NO;
    }
    return YES;
}

+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request
{
    return request;
}

- (void)startLoading
{
    id<NSURLProtocolClient> client = [self client];
    NSURLRequest *request = [self request];
    NSURL *url = [request URL];
    
    //是js给传值的请求
    if ([[url absoluteString]hasPrefix:@"http://test"]) {
        [self handelRequest];
        return;
    }
    
    //是本地文件
    if ([[url absoluteString]hasPrefix:@"file://"]) {
        //直接读取本地文件内容,作为response的内容
        NSData *data = [[NSData alloc]initWithContentsOfFile:[url path]];
        NSURLCacheStoragePolicy caching = NSURLCacheStorageAllowedInMemoryOnly;
        
        NSURLResponse *response = [[NSURLResponse alloc] initWithURL:url MIMEType:[[url path]pathExtension] expectedContentLength:[data length] textEncodingName:@"utf-8"];
        [client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:caching];
        [client URLProtocol:self didLoadData:data];
        [client URLProtocolDidFinishLoading:self];
    }
    //服务器上的文件
    else{
        //重新创建一个request
        NSMutableURLRequest *newRequest = [self.request mutableCopy];
        //标记是否创建过了该请求,不加标识会陷入一个死循环中
        [NSURLProtocol setProperty:@YES forKey:MyURLProtocolHandledKey inRequest:newRequest];
        //用nsurlconnection进行网络请求
        self.connection = [NSURLConnection connectionWithRequest:newRequest delegate:self];
    }

}

- (void) stopLoading {
    [self.connection cancel];
    self.mutableData = nil;
}

#pragma mark - NSURLConnectionDelegate

- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
    
    self.response = response;
    self.mutableData = [[NSMutableData alloc] init];
}

- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [self.client URLProtocol:self didLoadData:data];
    
    [self.mutableData appendData:data];
}

- (void) connectionDidFinishLoading:(NSURLConnection *)connection {
    [self.client URLProtocolDidFinishLoading:self];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    [self.client URLProtocol:self didFailWithError:error];
}

@end

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions中添加

[AppProtocolHandlerregisterSpecialProtocol];   这样所有的请求都会先让AppProtocolHandler过滤一遍的。


好了,关键的代码完成了,找一个viewcontroller添加一个uiwebview上去吧,然后加载测试的html:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    NSURL *url = [[NSBundle mainBundle] URLForResource:@"test" withExtension:@"html"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [self.webview loadRequest:request];
}

怕小伙伴们oc写久了,忘记了ajax怎么post请求,再附加一段可测试的html代码吧(也还是别人帮我写的偷笑):

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
            <title>Document</title>
            <script type="text/javascript" src="http://upcdn.b0.upaiyun.com/libs/jquery/jquery-1.9.1.min.js"></script>
            <script type="text/javascript">
                $(function(){
                  alert(1);
                  $('#btn').click(function(){
                                  
                                  alert('Pre Run Post Request');
                                  
                                  $.post("http://test/setTitle", {
                                         "key":"value"
                                         }, function(response){
                                         alert('Return Http Status OK');
                                         alert('Here the response: ' + response);
                                         });
                                  
                                  })
                  });
                </script>
    </head>
    <body>
        <button type="button" id="btn">Click Me</button>
    </body>
</html>

注:js里不会报错的,因为这个post根本没走网络,我就给了它一个长度为0的data作为响应。


参考链接:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值