美文网首页Weex开发技巧weex社区程序员
iOS 中 Weex网络监听、设置Cookie

iOS 中 Weex网络监听、设置Cookie

作者: LuisX | 来源:发表于2017-09-21 18:53 被阅读275次

    写在最开始,项目中需要监听Weex所有网络请求,设置cookie,监听网络异常,帮助团队查找weex网络问题等等,以及更好的扩展weex网络请求模块,因此在项目中实现WXSJResourceRequestHandlerDefaultImpl来处理weex网络请求。

    版本

    WeexSDK版本号:0.13.0

    一、Weex注册Handler

    在初始化WeexSDK时,需要注册自定义协议WXSJResourceRequestHandlerDefaultImpl用来实现Weex请求。

    其余为项目中,业务需要的模块、协议、组件。

    [WXSDKEngine initSDKEnvironment];
    //设置Log输出等级:调试环境默认为Debug,正式发布会自动关闭。
    // [WXLog setLogLevel:WXLogLevelAll];
    // [WXDebugTool setDebug:YES];
    [WXSDKEngine registerModule:@"shopBase" withClass:[BaseModule class]];
    [WXSDKEngine registerModule:@"shopModal" withClass:[ShopModule class]];
    [WXSDKEngine registerHandler:[WXImgLoaderDefaultImpl new] withProtocol:@protocol(WXImgLoaderProtocol)];
    [WXSDKEngine registerHandler:[WXSJNetworkDefaultlmpl new] withProtocol:@protocol(WXURLRewriteProtocol)];
    [WXSDKEngine registerHandler:[WXSJResourceRequestHandlerDefaultImpl new] withProtocol:@protocol(WXResourceRequestHandler)];
    [WXSDKEngine registerComponent:@"a" withClass:NSClassFromString(@"WXPushComponent")];
    [WXSDKEngine registerComponent:@"pager" withClass:NSClassFromString(@"WXSJPagerComponent")];
    

    二、WXSJResourceRequestHandlerDefaultImpl的实现

    WXSJResourceRequestHandlerDefaultImpl.h文件中

    此处的WeexHeader.h为项目中weex头文件汇总,按需导入就好。

    #import <Foundation/Foundation.h>
    #import "WeexHeader.h"
    
    @interface WXSJResourceRequestHandlerDefaultImpl : NSObject <WXResourceRequestHandler>
    
    @end
    

    WXSJResourceRequestHandlerDefaultImpl.m文件中

    使用NSURLSession实现底层Weex网络请求,所有网络请求都会经过这里。

    SJCookieHandle文件为项目中引用,对cookie进行处理的。(项目中,原生使用AFNNetwork携带cookie进行网络请求,Weex使用NSURLSession携带cookie网络请求,来确定用户身份)

    #import "WXSJResourceRequestHandlerDefaultImpl.h"
    #import "WXSJThreadSafeMutableDictionary.h"
    //#import "SJCookieHandle.h"
    
    @interface WXSJResourceRequestHandlerDefaultImpl () <NSURLSessionDataDelegate>
    
    @end
    
    @implementation WXSJResourceRequestHandlerDefaultImpl{
        NSURLSession *_session;
        WXSJThreadSafeMutableDictionary<NSURLSessionDataTask *, id<WXResourceRequestDelegate>> *_delegates;
    }
    #pragma mark - WXResourceRequestHandler
    // 发起请求
    - (void)sendRequest:(WXResourceRequest *)request withDelegate:(id<WXResourceRequestDelegate>)delegate{
        
        // 请求前setCookies
        // [[SJCookieHandle initSJCookieHandle] setCookiesFromArr];
        
        if (!_session) {
            NSURLSessionConfiguration *urlSessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
            if ([WXAppConfiguration customizeProtocolClasses].count > 0) {
                NSArray *defaultProtocols = urlSessionConfig.protocolClasses;
                urlSessionConfig.protocolClasses = [[WXAppConfiguration customizeProtocolClasses] arrayByAddingObjectsFromArray:defaultProtocols];
            }
            _session = [NSURLSession sessionWithConfiguration:urlSessionConfig
                                                     delegate:self
                                                delegateQueue:[NSOperationQueue mainQueue]];
            _delegates = [WXSJThreadSafeMutableDictionary new];
        }
        
        NSURLSessionDataTask *task = [_session dataTaskWithRequest:request];
        request.taskIdentifier = task;
        [_delegates setObject:delegate forKey:task];
        [task resume];
    }
    
    // 取消请求
    - (void)cancelRequest:(WXResourceRequest *)request{
        if ([request.taskIdentifier isKindOfClass:[NSURLSessionTask class]]) {
            NSURLSessionTask *task = (NSURLSessionTask *)request.taskIdentifier;
            [task cancel];
            [_delegates removeObjectForKey:task];
        }
    }
    
    #pragma mark - NSURLSessionTaskDelegate & NSURLSessionDataDelegate
    // 发送数据的进度
    - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend{
        id<WXResourceRequestDelegate> delegate = [_delegates objectForKey:task];
        [delegate request:(WXResourceRequest *)task.originalRequest didSendData:bytesSent totalBytesToBeSent:totalBytesExpectedToSend];
    }
    
    // 接受到服务响应
    - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)task didReceiveResponse:(NSURLResponse *)response  completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler{
        id<WXResourceRequestDelegate> delegate = [_delegates objectForKey:task];
        [delegate request:(WXResourceRequest *)task.originalRequest didReceiveResponse:(WXResourceResponse *)response];
        completionHandler(NSURLSessionResponseAllow);
    }
    
    // 接收到服务器响应数据
    - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)task didReceiveData:(NSData *)data{
        id<WXResourceRequestDelegate> delegate = [_delegates objectForKey:task];
        [delegate request:(WXResourceRequest *)task.originalRequest didReceiveData:data];
    }
    
    // 请求完成(成功或失败)
    - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
        
        id<WXResourceRequestDelegate> delegate = [_delegates objectForKey:task];
        if (error) {
            [delegate request:(WXResourceRequest *)task.originalRequest didFailWithError:error];
        }else {
            // 请求后saveCacheCookie
            // [[SJCookieHandle initSJCookieHandle] saveCacheCookie];
            [delegate requestDidFinishLoading:(WXResourceRequest *)task.originalRequest];
        }
        [_delegates removeObjectForKey:task];
        
        [self startWeexNetworkMonitoringErrorFeedBackWithTask:task error:error];
    }
    
    /*
    #ifdef __IPHONE_10_0
    - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics
    {
        id<WXResourceRequestDelegate> delegate = [_delegates objectForKey:task];
        [delegate request:(WXResourceRequest *)task.originalRequest didFinishCollectingMetrics:metrics];
    }
    #endif
    */
    
    WXSJThreadSafeMutableDictionary

    三、依赖WXSJThreadSafeMutableDictionary

    Weex官方Demo中实现的线程安全的MutableDictionary,实现Weex网络请求需要依赖这个文件,直接Copy就好。

    WXSJThreadSafeMutableDictionary.h中

    #import <Foundation/Foundation.h>
    
    @interface WXSJThreadSafeMutableDictionary<KeyType, ObjectType> : NSMutableDictionary
    
    @end
    

    WXSJThreadSafeMutableDictionary.m中

    #import "WXSJThreadSafeMutableDictionary.h"
    
    @interface WXSJThreadSafeMutableDictionary ()
    
    @property (nonatomic, strong) dispatch_queue_t queue;
    @property (nonatomic, strong) NSMutableDictionary* dict;
    
    @end
    
    @implementation WXSJThreadSafeMutableDictionary
    - (instancetype)initCommon
    {
        self = [super init];
        if (self) {
            NSString* uuid = [NSString stringWithFormat:@"com.taobao.weex.dictionary_%p", self];
            _queue = dispatch_queue_create([uuid UTF8String], DISPATCH_QUEUE_CONCURRENT);
        }
        return self;
    }
    
    - (instancetype)init
    {
        self = [self initCommon];
        if (self) {
            _dict = [NSMutableDictionary dictionary];
        }
        return self;
    }
    
    - (instancetype)initWithCapacity:(NSUInteger)numItems
    {
        self = [self initCommon];
        if (self) {
            _dict = [NSMutableDictionary dictionaryWithCapacity:numItems];
        }
        return self;
    }
    
    - (NSDictionary *)initWithContentsOfFile:(NSString *)path
    {
        self = [self initCommon];
        if (self) {
            _dict = [NSMutableDictionary dictionaryWithContentsOfFile:path];
        }
        return self;
    }
    
    - (instancetype)initWithCoder:(NSCoder *)aDecoder
    {
        self = [self initCommon];
        if (self) {
            _dict = [[NSMutableDictionary alloc] initWithCoder:aDecoder];
        }
        return self;
    }
    
    - (instancetype)initWithObjects:(const id [])objects forKeys:(const id<NSCopying> [])keys count:(NSUInteger)cnt
    {
        self = [self initCommon];
        if (self) {
            _dict = [NSMutableDictionary dictionary];
            for (NSUInteger i = 0; i < cnt; ++i) {
                _dict[keys[i]] = objects[i];
            }
            
        }
        return self;
    }
    
    - (NSUInteger)count
    {
        __block NSUInteger count;
        dispatch_sync(_queue, ^{
            count = _dict.count;
        });
        return count;
    }
    
    - (id)objectForKey:(id)aKey
    {
        __block id obj;
        dispatch_sync(_queue, ^{
            obj = _dict[aKey];
        });
        return obj;
    }
    
    - (NSEnumerator *)keyEnumerator
    {
        __block NSEnumerator *enu;
        dispatch_sync(_queue, ^{
            enu = [_dict keyEnumerator];
        });
        return enu;
    }
    
    - (void)setObject:(id)anObject forKey:(id<NSCopying>)aKey
    {
        aKey = [aKey copyWithZone:NULL];
        dispatch_barrier_async(_queue, ^{
            _dict[aKey] = anObject;
        });
    }
    
    - (void)removeObjectForKey:(id)aKey
    {
        dispatch_barrier_async(_queue, ^{
            [_dict removeObjectForKey:aKey];
        });
    }
    
    - (void)removeAllObjects{
        dispatch_barrier_async(_queue, ^{
            [_dict removeAllObjects];
        });
    }
    
    - (id)copy{
        __block id copyInstance;
        dispatch_sync(_queue, ^{
            copyInstance = [_dict copy];
        });
        return copyInstance;
    }
    @end
    

    参考

    incubator-weex官方GitHub中iOS的Network源码

    相关文章

      网友评论

      本文标题:iOS 中 Weex网络监听、设置Cookie

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