WEEX + HTTPDNS iOS解决方案
由于WebView
并未暴露处设置DNS的接口,因而在WebView
场景下使用HttpDns
存在很多无法限制,但如果接入WEEX
,则可以较好地植入HTTPDNS
,本文主要介绍在WEEX
场景下接入HTTPDNS
的方案细节。
在WEEX
运行时环境下,所有的逻辑最终都会转换到Native Runtime
中执行,网络请求也不例外。同时WEEX
也提供了自定义相应实现的接口,通过重写网络请求适配器,我们可以较为简单地接入HTTPDNS。在WEEX运行环境中,主要有两种网络请求:
下面以 weex iOS 0.7.0
版本为例:
Stream
网络请求 + HTTPDNS
Stream
网络请求在 iOS 端最终会通过WXNetworkDefaultImpl完成,同时WEEX
也提供了相应的接口自定义网络请求适配器。具体的逻辑如下:
第一步:创建自定义网络请求适配器,实现 WXNetworkHttpDnsImpl
接口
#import <WeexSDK/WeexSDK.h>
#import "WXNetworkDefaultImpl.h"
@interface WXNetworkHttpDnsImpl : NSObject<WXNetworkProtocol, WXModuleProtocol , NSURLSessionDelegate>
@end
第二步:在WEEX
初始化时注册自定义网络适配器,替换默认适配器:
[WXSDKEngine registerHandler:[WXNetworkHttpDnsImpl new] withProtocol:@protocol(WXNetworkProtocol)];
之后的网络请求都会通过WXNetworkHttpDnsImpl
实现,所以只需要在WXNetworkHttpDnsImpl
中植入 HTTPDNS 逻辑即可,具体逻辑可以参考如下代码:
#import "WXNetworkDefaultImpl.h"
@interface WXNetworkCallbackInfo : NSObject
@property (nonatomic, copy) void(^sendDataCallback)(int64_t, int64_t);
@property (nonatomic, copy) void(^responseCallback)(NSURLResponse *);
@property (nonatomic, copy) void(^receiveDataCallback)(NSData *);
@property (nonatomic, strong) NSMutableData *data;
@property (nonatomic, copy) void(^compeletionCallback)(NSData *, NSError *);
@end
@implementation WXNetworkCallbackInfo
@end
@implementation WXNetworkDefaultImpl
{
NSMutableDictionary *_callbacks;
NSURLSession *_session;
}
- (id)sendRequest:(NSURLRequest *)request withSendingData:(void (^)(int64_t, int64_t))sendDataCallback
withResponse:(void (^)(NSURLResponse *))responseCallback
withReceiveData:(void (^)(NSData *))receiveDataCallback
withCompeletion:(void (^)(NSData *, NSError *))compeletionCallback
{
WXNetworkCallbackInfo *info = [WXNetworkCallbackInfo new];
info.sendDataCallback = sendDataCallback;
info.responseCallback = responseCallback;
info.receiveDataCallback = receiveDataCallback;
info.compeletionCallback = compeletionCallback;
if (!_session) {
_session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]
delegate:self
delegateQueue:[NSOperationQueue mainQueue]];
}
NSURLSessionDataTask *task = [_session dataTaskWithRequest:request];
if (!_callbacks) {
_callbacks = [NSMutableDictionary dictionary];
}
[_callbacks setObject:info forKey:task];
[task resume];
return task;
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
didSendBodyData:(int64_t)bytesSent
totalBytesSent:(int64_t)totalBytesSent
totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
{
WXNetworkCallbackInfo *info = [_callbacks objectForKey:task];
if (info.sendDataCallback) {
info.sendDataCallback(totalBytesSent, totalBytesExpectedToSend);
}
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)task
didReceiveResponse:(NSURLResponse *)response
completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
{
WXNetworkCallbackInfo *info = [_callbacks objectForKey:task];
if (info.responseCallback) {
info.responseCallback(response);
}
completionHandler(NSURLSessionResponseAllow);
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)task didReceiveData:(NSData *)data
{
WXNetworkCallbackInfo *info = [_callbacks objectForKey:task];
if (info.receiveDataCallback) {
info.receiveDataCallback(data);
}
NSMutableData *mutableData = info.data;
if (!mutableData) {
mutableData = [NSMutableData new];
info.data = mutableData;
}
[mutableData appendData:data];
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
WXNetworkCallbackInfo *info = [_callbacks objectForKey:task];
if (info.compeletionCallback) {
info.compeletionCallback(info.data, error);
}
[_callbacks removeObjectForKey:task];
}
@end
1.2 <image>
网络请求 + HTTPDNS
WEEX
并没有提供默认的图片适配器实现,所以用户必须自行实现才能完成图片请求逻辑,具体步骤分为以下几步:
第一步:自定义图片请求适配器,实现IWXImgLoaderAdapter
接口
#import "WXImgLoaderProtocol.h"
@interface WXImgLoaderDefaultImpl : NSObject<WXImgLoaderProtocol, WXModuleProtocol>
@end
第二步:在WEEX
初始化时注册该图片适配器:
[WXSDKEngine registerHandler:[WXImgLoaderDefaultImpl new] withProtocol:@protocol(WXImgLoaderProtocol)];
所以同WXNetworkHttpDnsImpl
一样,我们只需在WXNetworkHttpDnsImpl
植入HTTPDNS
逻辑即可。