You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by ji...@apache.org on 2017/02/20 06:40:59 UTC

[10/50] [abbrv] incubator-weex git commit: V0.10.0 stable gitlab (#178)

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
index f0e605e..8fcf3bb 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
+++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
@@ -22,20 +22,37 @@
 #import "WXView.h"
 #import "WXRootView.h"
 #import "WXThreadSafeMutableDictionary.h"
+#import "WXResourceRequest.h"
+#import "WXResourceResponse.h"
+#import "WXResourceLoader.h"
+#import "WXSDKEngine.h"
 
 NSString *const bundleUrlOptionKey = @"bundleUrl";
 
 NSTimeInterval JSLibInitTime = 0;
 
+typedef enum : NSUInteger {
+    WXLoadTypeNormal,
+    WXLoadTypeBack,
+    WXLoadTypeForward,
+    WXLoadTypeReload,
+    WXLoadTypeReplace
+} WXLoadType;
+
 @implementation WXSDKInstance
 {
-    id<WXNetworkProtocol> _networkHandler;
+    NSDictionary *_options;
+    id _jsData;
+    
+    WXResourceLoader *_mainBundleLoader;
     WXComponentManager *_componentManager;
     WXRootView *_rootView;
+    WXThreadSafeMutableDictionary *_moduleEventObservers;
 }
 
-- (void) dealloc
+- (void)dealloc
 {
+    [_moduleEventObservers removeAllObjects];
     [self removeObservers];
     [[NSNotificationCenter defaultCenter] removeObserver:self];
 }
@@ -61,12 +78,19 @@ NSTimeInterval JSLibInitTime = 0;
         _moduleInstances = [NSMutableDictionary new];
         _styleConfigs = [NSMutableDictionary new];
         _attrConfigs = [NSMutableDictionary new];
+        _moduleEventObservers = [WXThreadSafeMutableDictionary new];
+        _trackComponent = NO;
        
         [self addObservers];
     }
     return self;
 }
 
+- (NSString *)description
+{
+    return [NSString stringWithFormat:@"<%@: %p; id = %@; rootView = %@; url= %@>", NSStringFromClass([self class]), self, _instanceId, _rootView, _scriptURL];
+}
+
 #pragma mark Public Mehtods
 
 - (UIView *)rootView
@@ -74,6 +98,22 @@ NSTimeInterval JSLibInitTime = 0;
     return _rootView;
 }
 
+
+- (void)setFrame:(CGRect)frame
+{
+    if (!CGRectEqualToRect(frame, _frame)) {
+        _frame = frame;
+        WXPerformBlockOnMainThread(^{
+            if (_rootView) {
+                _rootView.frame = frame;
+                WXPerformBlockOnComponentThread(^{
+                    [self.componentManager rootViewFrameDidChange:frame];
+                });
+            }
+        });
+    }
+}
+
 - (void)renderWithURL:(NSURL *)url
 {
     [self renderWithURL:url options:nil data:nil];
@@ -86,100 +126,22 @@ NSTimeInterval JSLibInitTime = 0;
         return;
     }
     
-    _scriptURL = url;
-    NSMutableDictionary *newOptions = [options mutableCopy];
-    if (!newOptions) {
-        newOptions = [[NSMutableDictionary alloc] init];
-    }
-    if (!newOptions[bundleUrlOptionKey]) {
-        newOptions[bundleUrlOptionKey] = url.absoluteString;
-    }
-    if ([newOptions[bundleUrlOptionKey] isKindOfClass:[NSURL class]]) {
-        newOptions[bundleUrlOptionKey] = ((NSURL*)newOptions[bundleUrlOptionKey]).absoluteString;
-    }
-    
-    if (!self.pageName || [self.pageName isEqualToString:@""]) {
-        self.pageName = [WXUtility urlByDeletingParameters:url].absoluteString ? : @"";
-    }
-    
-    __weak typeof(self) weakSelf = self;
-    if ([url isFileURL]) {
-        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
-            NSString *path = [url path];
-            NSData *scriptData = [[NSFileManager defaultManager] contentsAtPath:path];
-            NSString *script = [[NSString alloc] initWithData:scriptData encoding:NSUTF8StringEncoding];
-            if (!script || script.length <= 0) {
-                NSString *errorDesc = [NSString stringWithFormat:@"File read error at url: %@", url];
-                WXLogError(@"%@", errorDesc);
-                if (weakSelf.onFailed) {
-                    weakSelf.onFailed([NSError errorWithDomain:WX_ERROR_DOMAIN code:0 userInfo:@{NSLocalizedDescriptionKey: errorDesc}]);
-                }
-                return;
-            }
-            [weakSelf renderView:script options:newOptions data:data];
-        });
-    } else {
-        WX_MONITOR_INSTANCE_PERF_START(WXPTJSDownload, self);
-        
-        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
-        [request setValue:[WXUtility userAgent] forHTTPHeaderField:@"User-Agent"];
-        [request setValue:@"weex" forHTTPHeaderField:@"f-refer"];
-        
-        id<WXNetworkProtocol> networkHandler = [self networkHandler];
-        
-        __block NSURLResponse *urlResponse;
-        [networkHandler sendRequest:request
-                   withSendingData:^(int64_t bytesSent, int64_t totalBytes) {}
-                      withResponse:^(NSURLResponse *response) {
-                          urlResponse = response;
-                      }
-                   withReceiveData:^(NSData *data) {}
-                   withCompeletion:^(NSData *totalData, NSError *error) {
-            //TODO 304
-            if (!error && [urlResponse isKindOfClass:[NSHTTPURLResponse class]] && ((NSHTTPURLResponse *)urlResponse).statusCode != 200) {
-                error = [NSError errorWithDomain:WX_ERROR_DOMAIN
-                                            code:((NSHTTPURLResponse *)urlResponse).statusCode
-                                        userInfo:@{@"message":@"status code error."}];
-            }
-            
-            if (error) {
-                NSString *errorMessage = [NSString stringWithFormat:@"Connection to %@ occurs an error:%@", request.URL, error.localizedDescription];
-                WX_MONITOR_FAIL_ON_PAGE(WXMTJSDownload, WX_ERR_JSBUNDLE_DOWNLOAD, errorMessage, weakSelf.pageName);
-                
-                if (weakSelf.onFailed) {
-                    weakSelf.onFailed(error);
-                }
-                return;
-            }
-                       
-            if (!totalData) {
-                NSString *errorMessage = [NSString stringWithFormat:@"Connection to %@ but no data return", request.URL];
-                WX_MONITOR_FAIL_ON_PAGE(WXMTJSDownload, WX_ERR_JSBUNDLE_DOWNLOAD, errorMessage, weakSelf.pageName);
-                
-                if (weakSelf.onFailed) {
-                    weakSelf.onFailed(error);
-                }
-                return;
-            }
-                       
-            NSString *script = [[NSString alloc] initWithData:totalData encoding:NSUTF8StringEncoding];
-            if (!script) {
-                WX_MONITOR_FAIL_ON_PAGE(WXMTJSDownload, WX_ERR_JSBUNDLE_STRING_CONVERT, @"data converting to string failed.", weakSelf.pageName)
-                return;
-            }
-            
-            WX_MONITOR_SUCCESS_ON_PAGE(WXMTJSDownload, weakSelf.pageName);
-            WX_MONITOR_INSTANCE_PERF_END(WXPTJSDownload, weakSelf);
-
-            [weakSelf renderView:script options:newOptions data:data];
-        }];
-    }
+    WXResourceRequest *request = [WXResourceRequest requestWithURL:url resourceType:WXResourceTypeMainBundle referrer:@"" cachePolicy:NSURLRequestUseProtocolCachePolicy];
+    [self _renderWithRequest:request options:options data:data];
 }
 
 - (void)renderView:(NSString *)source options:(NSDictionary *)options data:(id)data
 {
-    WXLogDebug(@"Render view: %@, data:%@", self, [WXUtility JSONString:data]);
+    WXLogDebug(@"Render source: %@, data:%@", self, [WXUtility JSONString:data]);
+    
+    _options = options;
+    _jsData = data;
     
+    [self _renderWithMainBundleString:source];
+}
+
+- (void)_renderWithMainBundleString:(NSString *)mainBundleString
+{
     if (!self.instanceId) {
         WXLogError(@"Fail to find instance\uff01");
         return;
@@ -194,13 +156,13 @@ NSTimeInterval JSLibInitTime = 0;
     WX_MONITOR_INSTANCE_PERF_START(WXPTFirstScreenRender, self);
     WX_MONITOR_INSTANCE_PERF_START(WXPTAllRender, self);
     
-    NSMutableDictionary *dictionary = [options mutableCopy];
+    NSMutableDictionary *dictionary = [_options mutableCopy];
     if ([WXLog logLevel] >= WXLogLevelLog) {
         dictionary[@"debug"] = @(YES);
     }
     
     if ([WXDebugTool getReplacedBundleJS]) {
-        source = [WXDebugTool getReplacedBundleJS];
+        mainBundleString = [WXDebugTool getReplacedBundleJS];
     }
     
     //TODO WXRootView
@@ -211,30 +173,100 @@ NSTimeInterval JSLibInitTime = 0;
             self.onCreate(_rootView);
         }
     });
-
-    [[WXSDKManager bridgeMgr] createInstance:self.instanceId template:source options:dictionary data:data];
-
-    WX_MONITOR_PERF_SET(WXPTBundleSize, [source lengthOfBytesUsingEncoding:NSUTF8StringEncoding], self);
+    
+    // ensure default modules/components/handlers are ready before create instance
+    [WXSDKEngine registerDefaults];
+    
+    [[WXSDKManager bridgeMgr] createInstance:self.instanceId template:mainBundleString options:dictionary data:_jsData];
+    
+    WX_MONITOR_PERF_SET(WXPTBundleSize, [mainBundleString lengthOfBytesUsingEncoding:NSUTF8StringEncoding], self);
 }
 
-- (void)setFrame:(CGRect)frame
+
+- (void)_renderWithRequest:(WXResourceRequest *)request options:(NSDictionary *)options data:(id)data;
 {
-    if (!CGRectEqualToRect(frame, _frame)) {
-        _frame = frame;
-        WXPerformBlockOnMainThread(^{
-            if (_rootView) {
-                _rootView.frame = frame;
-                WXPerformBlockOnComponentThread(^{
-                    [self.componentManager rootViewFrameDidChange:frame];
-                });
-            }
-        });
+    NSURL *url = request.URL;
+    _scriptURL = url;
+    _options = options;
+    _jsData = data;
+    NSMutableDictionary *newOptions = [options mutableCopy] ?: [NSMutableDictionary new];
+    
+    if (!newOptions[bundleUrlOptionKey]) {
+        newOptions[bundleUrlOptionKey] = url.absoluteString;
     }
+    // compatible with some wrong type, remove this hopefully in the future.
+    if ([newOptions[bundleUrlOptionKey] isKindOfClass:[NSURL class]]) {
+        WXLogWarning(@"Error type in options with key:bundleUrl, should be of type NSString, not NSURL!");
+        newOptions[bundleUrlOptionKey] = ((NSURL*)newOptions[bundleUrlOptionKey]).absoluteString;
+    }
+    
+    if (!self.pageName || [self.pageName isEqualToString:@""]) {
+        self.pageName = [WXUtility urlByDeletingParameters:url].absoluteString ? : @"";
+    }
+    
+    request.userAgent = [WXUtility userAgent];
+    
+    WX_MONITOR_INSTANCE_PERF_START(WXPTJSDownload, self);
+    __weak typeof(self) weakSelf = self;
+    _mainBundleLoader = [[WXResourceLoader alloc] initWithRequest:request];;
+    _mainBundleLoader.onFinished = ^(WXResourceResponse *response, NSData *data) {
+        __strong typeof(weakSelf) strongSelf = weakSelf;
+        
+        if ([response isKindOfClass:[NSHTTPURLResponse class]] && ((NSHTTPURLResponse *)response).statusCode != 200) {
+            NSError *error = [NSError errorWithDomain:WX_ERROR_DOMAIN
+                                        code:((NSHTTPURLResponse *)response).statusCode
+                                    userInfo:@{@"message":@"status code error."}];
+            if (strongSelf.onFailed) {
+                strongSelf.onFailed(error);
+            }
+            return ;
+        }
+
+        if (!data) {
+            NSString *errorMessage = [NSString stringWithFormat:@"Request to %@ With no data return", request.URL];
+            WX_MONITOR_FAIL_ON_PAGE(WXMTJSDownload, WX_ERR_JSBUNDLE_DOWNLOAD, errorMessage, strongSelf.pageName);
+
+            if (strongSelf.onFailed) {
+                strongSelf.onFailed(error);
+            }
+            return;
+        }
+        
+        NSString *jsBundleString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
+        if (!jsBundleString) {
+            WX_MONITOR_FAIL_ON_PAGE(WXMTJSDownload, WX_ERR_JSBUNDLE_STRING_CONVERT, @"data converting to string failed.", strongSelf.pageName)
+            return;
+        }
+
+        WX_MONITOR_SUCCESS_ON_PAGE(WXMTJSDownload, strongSelf.pageName);
+        WX_MONITOR_INSTANCE_PERF_END(WXPTJSDownload, strongSelf);
+
+        [strongSelf _renderWithMainBundleString:jsBundleString];
+    };
+    
+    _mainBundleLoader.onFailed = ^(NSError *loadError) {
+        NSString *errorMessage = [NSString stringWithFormat:@"Request to %@ occurs an error:%@", request.URL, loadError.localizedDescription];
+        WX_MONITOR_FAIL_ON_PAGE(WXMTJSDownload, WX_ERR_JSBUNDLE_DOWNLOAD, errorMessage, weakSelf.pageName);
+        
+        if (weakSelf.onFailed) {
+            weakSelf.onFailed(loadError);
+        }
+    };
+    
+    [_mainBundleLoader start];
 }
 
-- (void)reloadData:(id)data
+- (void)reload:(BOOL)forcedReload
 {
-    [self refreshInstance:data];
+    // TODO: [self unload]
+    if (!_scriptURL) {
+        WXLogError(@"No script URL found while reloading!");
+        return;
+    }
+    
+    NSURLRequestCachePolicy cachePolicy = forcedReload ? NSURLRequestReloadIgnoringCacheData : NSURLRequestUseProtocolCachePolicy;
+    WXResourceRequest *request = [WXResourceRequest requestWithURL:_scriptURL resourceType:WXResourceTypeMainBundle referrer:_scriptURL.absoluteString cachePolicy:cachePolicy];
+    [self _renderWithRequest:request options:_options data:_jsData];
 }
 
 - (void)refreshInstance:(id)data
@@ -279,7 +311,7 @@ NSTimeInterval JSLibInitTime = 0;
     [data setObject:[NSString stringWithFormat:@"%ld",(long)state] forKey:@"state"];
     //[[WXSDKManager bridgeMgr] updateState:self.instanceId data:data];
     
-    [[NSNotificationCenter defaultCenter]postNotificationName:WX_INSTANCE_NOTIFICATION_UPDATE_STATE object:self userInfo:data];
+    [[NSNotificationCenter defaultCenter] postNotificationName:WX_INSTANCE_NOTIFICATION_UPDATE_STATE object:self userInfo:data];
 }
 
 - (id)moduleForClass:(Class)moduleClass
@@ -312,16 +344,6 @@ NSTimeInterval JSLibInitTime = 0;
     return [_componentManager numberOfComponents];
 }
 
-- (void)finishPerformance
-{
-    //deperacated
-}
-
-- (void)creatFinish
-{
-    
-}
-
 - (void)fireGlobalEvent:(NSString *)eventName params:(NSDictionary *)params
 {
     if (!params){
@@ -334,6 +356,26 @@ NSTimeInterval JSLibInitTime = 0;
     [[NSNotificationCenter defaultCenter] postNotificationName:eventName object:self userInfo:userInfo];
 }
 
+- (void)fireModuleEvent:(Class)module eventName:(NSString *)eventName params:(NSDictionary*)params
+{
+    NSDictionary * userInfo = @{
+                                @"moduleId":NSStringFromClass(module)?:@"",
+                                @"param":params?:@{},
+                                @"eventName":eventName
+                                };
+    
+    [[NSNotificationCenter defaultCenter] postNotificationName:WX_MODULE_EVENT_FIRE_NOTIFICATION object:self userInfo:userInfo];
+}
+
+- (CGFloat)pixelScaleFactor
+{
+    if (self.viewportWidth > 0) {
+        return [WXUtility portraitScreenSize].width / self.viewportWidth;
+    } else {
+        return [WXUtility defaultPixelScaleFactor];
+    }
+}
+
 - (NSURL *)completeURL:(NSString *)url
 {
     if (!_scriptURL) {
@@ -349,10 +391,107 @@ NSTimeInterval JSLibInitTime = 0;
     return [NSURL URLWithString:url relativeToURL:_scriptURL];
 }
 
+- (BOOL)checkModuleEventRegistered:(NSString*)event moduleClassName:(NSString*)moduleClassName
+{
+    NSDictionary * observer = [_moduleEventObservers objectForKey:moduleClassName];
+    return observer && observer[event]? YES:NO;
+}
+
 #pragma mark Private Methods
 
+- (void)_addModuleEventObserversWithModuleMethod:(WXModuleMethod *)method
+{
+    if ([method.arguments count] < 2) {
+        WXLogError(@"please check your method parameter!!");
+        return;
+    }
+    if(![method.arguments[0] isKindOfClass:[NSString class]]) {
+        // arguments[0] will be event name, so it must be a string type value here.
+        return;
+    }
+    NSMutableArray * methodArguments = [method.arguments mutableCopy];
+    if ([methodArguments count] == 2) {
+        [methodArguments addObject:@{@"once": @false}];
+    }
+    if (![methodArguments[2] isKindOfClass:[NSDictionary class]]) {
+        //arguments[2] is the option value, so it must be a dictionary.
+        return;
+    }
+    Class moduleClass =  [WXModuleFactory classWithModuleName:method.moduleName];
+    NSMutableDictionary * option = [methodArguments[3] mutableCopy];
+    [option setObject:method.moduleName forKey:@"moduleName"];
+    // the value for moduleName in option is for the need of callback
+    [self addModuleEventObservers:methodArguments[0] callback:methodArguments[1] option:option moduleClassName:NSStringFromClass(moduleClass)];
+}
+
+- (void)addModuleEventObservers:(NSString*)event callback:(NSString*)callbackId option:(NSDictionary *)option moduleClassName:(NSString*)moduleClassName
+{
+    BOOL once = [[option objectForKey:@"once"] boolValue];
+    NSString * moduleName = [option objectForKey:@"moduleName"];
+    NSMutableDictionary * observer = nil;
+    NSDictionary * callbackInfo = @{@"callbackId":callbackId,@"once":@(once),@"moduleName":moduleName};
+    if(![self checkModuleEventRegistered:event moduleClassName:moduleClassName]) {
+        //had not registered yet
+        observer = [NSMutableDictionary new];
+        [observer setObject:[@{event:[@[callbackInfo] mutableCopy]} mutableCopy] forKey:moduleClassName];
+        [_moduleEventObservers addEntriesFromDictionary:observer];
+    } else {
+        observer = _moduleEventObservers[moduleClassName];
+        [[observer objectForKey:event] addObject:callbackInfo];
+    }
+}
+
+- (void)_removeModuleEventObserverWithModuleMethod:(WXModuleMethod *)method
+{
+    if (![method.arguments count] && [method.arguments[0] isKindOfClass:[NSString class]]) {
+        return;
+    }
+    Class moduleClass =  [WXModuleFactory classWithModuleName:method.moduleName];
+    [self removeModuleEventObserver:method.arguments[0] moduleClassName:NSStringFromClass(moduleClass)];
+}
+
+- (void)removeModuleEventObserver:(NSString*)event moduleClassName:(NSString*)moduleClassName
+{
+    if (![self checkModuleEventRegistered:event moduleClassName:moduleClassName]) {
+        return;
+    }
+    [_moduleEventObservers[moduleClassName] removeObjectForKey:event];
+}
+
+- (void)moduleEventNotification:(NSNotification *)notification
+{
+    NSMutableDictionary *moduleEventObserversCpy = (NSMutableDictionary *)CFBridgingRelease(CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFDictionaryRef)_moduleEventObservers, kCFPropertyListMutableContainers));// deep
+    NSDictionary * userInfo = notification.userInfo;
+    NSMutableArray * listeners = [moduleEventObserversCpy[userInfo[@"moduleId"]] objectForKey:userInfo[@"eventName"]];
+    if (![listeners isKindOfClass:[NSArray class]]) {
+        return;
+        // something wrong
+    }
+    for (int i = 0;i < [listeners count]; i ++) {
+        NSDictionary * callbackInfo = listeners[i];
+        NSString *callbackId = callbackInfo[@"callbackId"];
+        BOOL once = [callbackInfo[@"once"] boolValue];
+        NSDictionary * retData = @{@"type":userInfo[@"eventName"],
+                                   @"module":callbackInfo[@"moduleName"],
+                                   @"data":userInfo[@"param"]};
+        [[WXSDKManager bridgeMgr] callBack:self.instanceId funcId:callbackId params:retData keepAlive:!once];
+        // if callback function is not once, then it is keepalive
+        if (once) {
+            NSMutableArray * moduleEventListener = [_moduleEventObservers[userInfo[@"moduleId"]] objectForKey:userInfo[@"eventName"]];
+            [moduleEventListener removeObject:callbackInfo];
+            if ([moduleEventListener count] == 0) {
+                [self removeModuleEventObserver:userInfo[@"eventName"] moduleClassName:userInfo[@"moduleId"]];
+            }
+            // if callback function is once. clear it after fire it.
+        }
+    }
+}
+
 - (void)addObservers
 {
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moduleEventNotification:) name:WX_MODULE_EVENT_FIRE_NOTIFICATION object:nil];
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil];
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil];
     [self addObserver:self forKeyPath:@"state" options:NSKeyValueObservingOptionNew context:nil];
 }
 
@@ -361,6 +500,16 @@ NSTimeInterval JSLibInitTime = 0;
     [self removeObserver:self forKeyPath:@"state"];
 }
 
+- (void)applicationWillResignActive:(NSNotification*)notification
+{
+    [self fireGlobalEvent:WX_APPLICATION_WILL_RESIGN_ACTIVE params:nil];
+}
+
+- (void)applicationDidBecomeActive:(NSNotification*)notification
+{
+    [self fireGlobalEvent:WX_APPLICATION_DID_BECOME_ACTIVE params:nil];
+}
+
 - (WXComponentManager *)componentManager
 {
     if (!_componentManager) {
@@ -370,15 +519,6 @@ NSTimeInterval JSLibInitTime = 0;
     return _componentManager;
 }
 
-- (id<WXNetworkProtocol>)networkHandler
-{
-    if (!_networkHandler) {
-        _networkHandler = [WXHandlerFactory handlerForProtocol:@protocol(WXNetworkProtocol)];
-    }
-    
-    return _networkHandler;
-}
-
 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
 {
     if ([keyPath isEqualToString:@"state"]) {
@@ -392,3 +532,24 @@ NSTimeInterval JSLibInitTime = 0;
 }
 
 @end
+
+@implementation WXSDKInstance (Deprecated)
+
+# pragma mark - Deprecated
+
+- (void)reloadData:(id)data
+{
+    [self refreshInstance:data];
+}
+
+- (void)finishPerformance
+{
+    //deperacated
+}
+
+- (void)creatFinish
+{
+    
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h
index 3ec3059..0bddbf9 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h
+++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_private.h
@@ -9,9 +9,12 @@
 #import <Foundation/Foundation.h>
 #import "WXSDKInstance.h"
 #import "WXComponentManager.h"
+#import "WXModuleMethod.h"
 
 @interface WXSDKInstance ()
 
+@property (nonatomic, assign) CGFloat viewportWidth;
+
 @property (nonatomic, strong) NSMutableDictionary *moduleInstances;
 @property (nonatomic, strong) NSMutableDictionary *naviBarStyles;
 @property (nonatomic, strong) NSMutableDictionary *styleConfigs;
@@ -19,4 +22,9 @@
 
 @property (nonatomic, readonly, strong) WXComponentManager *componentManager;
 
+- (void)addModuleEventObservers:(NSString*)event callback:(NSString*)callbackId option:(NSDictionary*)option moduleClassName:(NSString*)moduleClassName;
+- (void)_addModuleEventObserversWithModuleMethod:(WXModuleMethod*)method;
+- (void)removeModuleEventObserver:(NSString*)event moduleClassName:(NSString*)moduleClassName;
+- (void)_removeModuleEventObserverWithModuleMethod:(WXModuleMethod*)method;
+
 @end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m b/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m
index 2197299..2af32c5 100644
--- a/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m
+++ b/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m
@@ -12,6 +12,10 @@
 #import "WXTransform.h"
 #import "WXUtility.h"
 
+@interface WXAnimationModule ()
+
+@end
+
 @implementation WXAnimationModule
 
 @synthesize weexInstance;
@@ -57,10 +61,11 @@ WX_EXPORT_METHOD(@selector(transition:args:callback:))
     for (NSString *property in styles) {
         if ([property isEqualToString:@"transform"]) {
             NSString *transformOrigin = styles[@"transformOrigin"];
-            WXTransform *wxTransform = [WXTransform new];
+            WXTransform *wxTransform = [[WXTransform alloc] initWithInstance:self.weexInstance];
             transform = [wxTransform getTransform:styles[property] withView:view withOrigin:transformOrigin isTransformRotate:NO];
             rotateAngle = [wxTransform getRotateAngle];
-            if (rotateAngle > M_PI+0.0001) {
+            CGFloat originAngle = [self getRotateAngleFromTransForm:layer.transform];
+            if (fabs(originAngle - rotateAngle) > M_PI + 0.0001) {
                 /**
                  Rotate >= 180 degree not working on UIView block animation, have not found any more elegant solution than using CAAnimation
                  See http://stackoverflow.com/questions/9844925/uiview-infinite-360-degree-rotation-animation
@@ -75,10 +80,10 @@ WX_EXPORT_METHOD(@selector(transition:args:callback:))
             opacity = [styles[property] floatValue];
             isAnimateOpacity = YES;
         } else if ([property isEqualToString:@"width"]) {
-            newFrame = CGRectMake(newFrame.origin.x, newFrame.origin.y, [WXConvert WXPixelType:styles[property]], newFrame.size.height);
+            newFrame = CGRectMake(newFrame.origin.x, newFrame.origin.y, [WXConvert WXPixelType:styles[property] scaleFactor:self.weexInstance.pixelScaleFactor], newFrame.size.height);
             isAnimateFrame = YES;
         } else if ([property isEqualToString:@"height"]) {
-            newFrame = CGRectMake(newFrame.origin.x, newFrame.origin.y, newFrame.size.width, [WXConvert WXPixelType:styles[property]]);
+            newFrame = CGRectMake(newFrame.origin.x, newFrame.origin.y, newFrame.size.width, [WXConvert WXPixelType:styles[property] scaleFactor:self.weexInstance.pixelScaleFactor]);
             isAnimateFrame = YES;
         }
     }
@@ -91,6 +96,10 @@ WX_EXPORT_METHOD(@selector(transition:args:callback:))
     [CATransaction begin];
     [CATransaction setAnimationTimingFunction:[WXConvert CAMediaTimingFunction:args[@"timingFunction"]]];
     [CATransaction setCompletionBlock:^{
+        if (isUsingCAAnimation) {
+            CGAffineTransform originTransform = CATransform3DGetAffineTransform(layer.transform);
+            layer.transform = CATransform3DMakeAffineTransform(CGAffineTransformRotate(originTransform, rotateAngle * M_PI / 180));
+        }
         if (callback) {
             callback(@"SUCCESS");
         }
@@ -100,6 +109,7 @@ WX_EXPORT_METHOD(@selector(transition:args:callback:))
         CABasicAnimation* rotationAnimation;
         rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
         rotationAnimation.toValue = [NSNumber numberWithFloat: rotateAngle];
+        rotationAnimation.fromValue = @([self getRotateAngleFromTransForm:layer.transform]);
         rotationAnimation.duration = duration;
         rotationAnimation.cumulative = YES;
         rotationAnimation.fillMode = kCAFillModeForwards;
@@ -139,4 +149,12 @@ WX_EXPORT_METHOD(@selector(transition:args:callback:))
     [CATransaction commit];
 }
 
+- (CGFloat)getRotateAngleFromTransForm:(CATransform3D)transform
+{
+    CGAffineTransform cgTransform = CATransform3DGetAffineTransform(transform);
+    CGFloat radians = atan2f(cgTransform.b, cgTransform.a);
+    CGFloat degrees = radians * (180 / M_PI);
+    return degrees;
+}
+
 @end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Module/WXDomModule.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Module/WXDomModule.m b/ios/sdk/WeexSDK/Sources/Module/WXDomModule.m
index d0d85cc..cd97795 100644
--- a/ios/sdk/WeexSDK/Sources/Module/WXDomModule.m
+++ b/ios/sdk/WeexSDK/Sources/Module/WXDomModule.m
@@ -168,21 +168,20 @@ WX_EXPORT_METHOD(@selector(getComponentRect:callback:))
 }
 
 - (void)getComponentRect:(NSString*)ref callback:(WXModuleKeepAliveCallback)callback {
-    
     [self performBlockOnComponentMananger:^(WXComponentManager * manager) {
         NSMutableDictionary * callbackRsp = [[NSMutableDictionary alloc] init];
         UIView *rootView = manager.weexInstance.rootView;
-        CGRect rootRect = [rootView.superview convertRect:rootView.frame toView:rootView.superview.superview];
-        CGFloat resize = WXScreenResizeRadio();
+        CGRect rootRect = [rootView.superview convertRect:rootView.frame toView:rootView];
+        CGFloat scaleFactor = self.weexInstance.pixelScaleFactor;
         if ([ref isEqualToString:@"viewport"]) {
             [callbackRsp setObject:@(true) forKey:@"result"];
             [callbackRsp setObject:@{
-                                     @"width":@(rootRect.size.width/resize),
-                                     @"height":@(rootRect.size.height/resize),
-                                     @"bottom":@(CGRectGetMaxY(rootRect)/WXScreenResizeRadio()),
-                                     @"left":@(rootRect.origin.x/resize),
-                                     @"right":@(CGRectGetMaxX(rootRect)/resize),
-                                     @"top":@(rootRect.origin.y/resize)
+                                     @"width":@(rootRect.size.width / scaleFactor),
+                                     @"height":@(rootRect.size.height / scaleFactor),
+                                     @"bottom":@(CGRectGetMaxY(rootRect) / scaleFactor),
+                                     @"left":@(rootRect.origin.x / scaleFactor),
+                                     @"right":@(CGRectGetMaxX(rootRect) / scaleFactor),
+                                     @"top":@(rootRect.origin.y / scaleFactor)
                                      } forKey:@"size"];
             callback(callbackRsp, false);
         }else {
@@ -192,15 +191,15 @@ WX_EXPORT_METHOD(@selector(getComponentRect:callback:))
                     [callbackRsp setObject:@(false) forKey:@"result"];
                     [callbackRsp setObject:[NSString stringWithFormat:@"Illegal parameter, no ref about \"%@\" can be found",ref] forKey:@"errMsg"];
                 } else {
-                    CGRect componentRect = [component.view.superview convertRect:component.calculatedFrame toView:rootView.superview.superview];
+                    CGRect componentRect = [component.view.superview convertRect:component.calculatedFrame toView:rootView];
                     [callbackRsp setObject:@(true)forKey:@"result"];
                     [callbackRsp setObject:@{
-                                             @"width":@(componentRect.size.width /resize),
-                                             @"height":@(componentRect.size.height / resize),
-                                             @"bottom":@(CGRectGetMaxY(componentRect) / resize),
-                                             @"left":@(componentRect.origin.x / resize),
-                                             @"right":@(CGRectGetMaxX(componentRect) / resize),
-                                             @"top":@(componentRect.origin.y / resize)
+                                             @"width":@(componentRect.size.width / scaleFactor),
+                                             @"height":@(componentRect.size.height / scaleFactor),
+                                             @"bottom":@(CGRectGetMaxY(componentRect) / scaleFactor),
+                                             @"left":@(componentRect.origin.x / scaleFactor),
+                                             @"right":@(CGRectGetMaxX(componentRect) / scaleFactor),
+                                             @"top":@(componentRect.origin.y / scaleFactor)
                                              } forKey:@"size"];
                 }
                 callback(callbackRsp, false);

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Module/WXGlobalEventModule.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Module/WXGlobalEventModule.m b/ios/sdk/WeexSDK/Sources/Module/WXGlobalEventModule.m
index bd5bbc1..4eb8cf8 100644
--- a/ios/sdk/WeexSDK/Sources/Module/WXGlobalEventModule.m
+++ b/ios/sdk/WeexSDK/Sources/Module/WXGlobalEventModule.m
@@ -46,7 +46,7 @@ WX_EXPORT_METHOD(@selector(removeEventListener:))
 {
     if (_eventCallback[event]) {
         [_eventCallback removeObjectForKey:event];
-        [[NSNotificationCenter defaultCenter] removeObserver:self name:event object:weexInstance];
+        [[NSNotificationCenter defaultCenter] removeObserver:self name:event object:nil];
     } else {
         WXLogWarning(@"eventName \"%@\" doesn't exist", event);
     }
@@ -70,4 +70,10 @@ WX_EXPORT_METHOD(@selector(removeEventListener:))
     }
 }
 
+- (void)dealloc
+{
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
+    [_eventCallback removeAllObjects];
+}
+
 @end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Module/WXMetaModule.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Module/WXMetaModule.h b/ios/sdk/WeexSDK/Sources/Module/WXMetaModule.h
new file mode 100644
index 0000000..7d5c80c
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Module/WXMetaModule.h
@@ -0,0 +1,14 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+#import <Foundation/Foundation.h>
+#import "WXModuleProtocol.h"
+
+@interface WXMetaModule : NSObject <WXModuleProtocol>
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Module/WXMetaModule.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Module/WXMetaModule.m b/ios/sdk/WeexSDK/Sources/Module/WXMetaModule.m
new file mode 100644
index 0000000..3fa4f66
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Module/WXMetaModule.m
@@ -0,0 +1,40 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+#import "WXMetaModule.h"
+#import "WXConvert.h"
+#import "WXUtility.h"
+#import "WXSDKInstance_private.h"
+
+@implementation WXMetaModule
+
+@synthesize weexInstance;
+
+WX_EXPORT_METHOD(@selector(setViewport:))
+
+- (void)setViewport:(NSDictionary *)viewportArguments
+{
+    CGFloat viewportWidthFloat;
+    id viewportWidth = viewportArguments[@"width"];
+    if ([viewportWidth isKindOfClass:[NSString class]]) {
+        if ([viewportWidth isEqualToString:@"device-width"]) {
+            viewportWidthFloat = [WXUtility portraitScreenSize].width * WXScreenScale();
+        } else if ([viewportWidth isEqualToString:@"device-height"]) {
+            viewportWidthFloat = [WXUtility portraitScreenSize].height * WXScreenScale();
+        } else {
+            viewportWidthFloat = [WXConvert CGFloat:viewportWidth];
+        }
+    } else {
+        viewportWidthFloat = [WXConvert CGFloat:viewportWidth];
+    }
+    
+    if (viewportWidthFloat > 0) {
+        self.weexInstance.viewportWidth = viewportWidthFloat;
+    }
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Module/WXNavigatorModule.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Module/WXNavigatorModule.m b/ios/sdk/WeexSDK/Sources/Module/WXNavigatorModule.m
index b20f566..5569866 100644
--- a/ios/sdk/WeexSDK/Sources/Module/WXNavigatorModule.m
+++ b/ios/sdk/WeexSDK/Sources/Module/WXNavigatorModule.m
@@ -18,9 +18,10 @@
 
 @synthesize weexInstance;
 
+WX_EXPORT_METHOD(@selector(open:success:failure:))
+WX_EXPORT_METHOD(@selector(close:success:failure:))
 WX_EXPORT_METHOD(@selector(push:callback:))
 WX_EXPORT_METHOD(@selector(pop:callback:))
-WX_EXPORT_METHOD(@selector(close:callback:))
 WX_EXPORT_METHOD(@selector(setNavBarBackgroundColor:callback:))
 WX_EXPORT_METHOD(@selector(setNavBarLeftItem:callback:))
 WX_EXPORT_METHOD(@selector(clearNavBarLeftItem:callback:))
@@ -40,33 +41,36 @@ WX_EXPORT_METHOD(@selector(setNavBarHidden:callback:))
 
 #pragma mark Weex Application Interface
 
-- (void)push:(NSDictionary *)param callback:(WXModuleCallback)callback
+- (void)open:(NSDictionary *)param success:(WXModuleCallback)success failure:(WXModuleCallback)failure
 {
     id<WXNavigationProtocol> navigator = [self navigator];
     UIViewController *container = self.weexInstance.viewController;
-    [navigator pushViewControllerWithParam:param completion:^(NSString *code, NSDictionary *responseData) {
-        if (callback && code) {
-            callback(code);
-        }
-    } withContainer:container];
+    [navigator open:param success:success failure:failure withContainer:container];
 }
-
-- (void)pop:(NSDictionary *)param callback:(WXModuleCallback)callback
+    
+- (void)close:(NSDictionary *)param success:(WXModuleCallback)success failure:(WXModuleCallback)failure
 {
     id<WXNavigationProtocol> navigator = [self navigator];
     UIViewController *container = self.weexInstance.viewController;
-    [navigator popViewControllerWithParam:param completion:^(NSString *code, NSDictionary *responseData) {
+    [navigator close:param success:success failure:failure withContainer:container];
+}
+    
+- (void)push:(NSDictionary *)param callback:(WXModuleCallback)callback
+{
+    id<WXNavigationProtocol> navigator = [self navigator];
+    UIViewController *container = self.weexInstance.viewController;
+    [navigator pushViewControllerWithParam:param completion:^(NSString *code, NSDictionary *responseData) {
         if (callback && code) {
             callback(code);
         }
     } withContainer:container];
 }
 
-- (void)close:(NSDictionary *)param callback:(WXModuleCallback)callback
+- (void)pop:(NSDictionary *)param callback:(WXModuleCallback)callback
 {
     id<WXNavigationProtocol> navigator = [self navigator];
     UIViewController *container = self.weexInstance.viewController;
-    [navigator popToRootViewControllerWithParam:param completion:^(NSString *code, NSDictionary *responseData) {
+    [navigator popViewControllerWithParam:param completion:^(NSString *code, NSDictionary *responseData) {
         if (callback && code) {
             callback(code);
         }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Module/WXStreamModule.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Module/WXStreamModule.h b/ios/sdk/WeexSDK/Sources/Module/WXStreamModule.h
index be1e75d..2eb949f 100644
--- a/ios/sdk/WeexSDK/Sources/Module/WXStreamModule.h
+++ b/ios/sdk/WeexSDK/Sources/Module/WXStreamModule.h
@@ -12,6 +12,6 @@
 @interface WXStreamModule : NSObject <WXModuleProtocol>
 
 - (void)fetch:(NSDictionary *)options callback:(WXModuleCallback)callback progressCallback:(WXModuleKeepAliveCallback)progressCallback;
-- (void)sendHttp:(NSDictionary*)param callback:(WXModuleCallback)callback;
+- (void)sendHttp:(NSDictionary*)param callback:(WXModuleCallback)callback DEPRECATED_MSG_ATTRIBUTE("Use fetch method instead.");
 
 @end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Module/WXStreamModule.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Module/WXStreamModule.m b/ios/sdk/WeexSDK/Sources/Module/WXStreamModule.m
index 594c0d2..021699a 100644
--- a/ios/sdk/WeexSDK/Sources/Module/WXStreamModule.m
+++ b/ios/sdk/WeexSDK/Sources/Module/WXStreamModule.m
@@ -12,6 +12,7 @@
 #import "WXHandlerFactory.h"
 #import "WXNetworkProtocol.h"
 #import "WXURLRewriteProtocol.h"
+#import "WXResourceLoader.h"
 
 @implementation WXStreamModule
 
@@ -20,40 +21,6 @@
 WX_EXPORT_METHOD(@selector(sendHttp:callback:))
 WX_EXPORT_METHOD(@selector(fetch:callback:progressCallback:))
 
-- (void)sendHttp:(NSDictionary*)param callback:(WXModuleCallback)callback
-{
-    NSString* method = [param objectForKey:@"method"];
-    NSString* urlStr = [param objectForKey:@"url"];
-    NSDictionary* header = [param objectForKey:@"header"];
-    NSString* body = [param objectForKey:@"body"];
-    
-    NSURL *url = [NSURL URLWithString:urlStr];
-    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
-    [request setHTTPMethod:method];
-    [request setTimeoutInterval:60.0];
-    [request setValue:[WXUtility userAgent] forHTTPHeaderField:@"User-Agent"];
-    for (NSString *key in header) {
-        NSString *value = [header objectForKey:key];
-        [request setValue:value forHTTPHeaderField:key];
-    }
-    [request setHTTPBody:[body dataUsingEncoding:NSUTF8StringEncoding]];
-    
-    id<WXNetworkProtocol> networkHandler = [WXHandlerFactory handlerForProtocol:@protocol(WXNetworkProtocol)];
-    
-    [networkHandler sendRequest:request
-                withSendingData:^(int64_t bytesSent, int64_t totalBytes) {
-                 } withResponse:^(NSURLResponse *response) {
-              } withReceiveData:^(NSData *data) {
-              } withCompeletion:^(NSData *totalData, NSError *error) {
-                    NSString *responseData = nil;
-                    if (!error) {
-                        responseData = [[NSString alloc] initWithData:totalData encoding:NSUTF8StringEncoding];
-                    }
-                    //else ok
-                    callback(responseData);
-              }];
-}
-
 - (void)fetch:(NSDictionary *)options callback:(WXModuleCallback)callback progressCallback:(WXModuleKeepAliveCallback)progressCallback
 {
     __block NSInteger received = 0;
@@ -79,98 +46,117 @@ WX_EXPORT_METHOD(@selector(fetch:callback:progressCallback:))
     }
     urlStr = newUrlStr;
     NSDictionary *headers = [options objectForKey:@"headers"];
-    NSString *body = [options objectForKey:@"body"];
     NSString *type = [options objectForKey:@"type"];
     NSURL *url = [NSURL URLWithString:urlStr];
-    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
-    [request setHTTPMethod:method];
-    [request setValue:[WXUtility userAgent] forHTTPHeaderField:@"User-Agent"];
     
+    //TODO:referrer
+    WXResourceRequest *request = [WXResourceRequest requestWithURL:url resourceType:WXResourceTypeOthers referrer:nil cachePolicy:NSURLRequestUseProtocolCachePolicy];
+    request.HTTPMethod = method;
     if ([options valueForKey:@"timeout"]){
         //ms
         [request setTimeoutInterval:([[options valueForKey:@"timeout"] floatValue])/1000];
     }
+    request.userAgent = [WXUtility userAgent];
     
     for (NSString *header in headers) {
         NSString *value = [headers objectForKey:header];
         [request setValue:value forHTTPHeaderField:header];
     }
-    [request setHTTPBody:[body dataUsingEncoding:NSUTF8StringEncoding]];
 
-    [callbackRsp setObject:@{ @"OPENED": @1 } forKey:@"readyState"];
+    if ([options objectForKey:@"body"]) {
+        NSData * body = nil;
+        if ([[options objectForKey:@"body"] isKindOfClass:[NSString class]]) {
+            // compatible with the string body
+            body = [[options objectForKey:@"body"] dataUsingEncoding:NSUTF8StringEncoding];
+        }
+        if ([[options objectForKey:@"body"] isKindOfClass:[NSDictionary class]]) {
+            body = [[WXUtility JSONString:[options objectForKey:@"body"]] dataUsingEncoding:NSUTF8StringEncoding];
+        }
+        if (!body) {
+            [callbackRsp setObject:@(-1) forKey:@"status"];
+            [callbackRsp setObject:@false forKey:@"ok"];
+            callback(callbackRsp);
+                
+            return;
+        }
+        
+        [request setHTTPBody:body];
+    }
     
+    [callbackRsp setObject:@{ @"OPENED": @1 } forKey:@"readyState"];
     progressCallback(callbackRsp, TRUE);
     
-    id<WXNetworkProtocol> networkHandler = [WXHandlerFactory handlerForProtocol:@protocol(WXNetworkProtocol)];
-    __block NSString *respEncode = nil;
+    WXResourceLoader *loader = [[WXResourceLoader alloc] initWithRequest:request];
     __weak typeof(self) weakSelf = self;
-    [networkHandler sendRequest:request
-                withSendingData:^(int64_t bytesSent, int64_t totalBytes) {
-                } withResponse:^(NSURLResponse *response) {
-                    httpResponse = (NSHTTPURLResponse*)response;
-                    respEncode = httpResponse.textEncodingName;
-                    if (weakSelf) {
-                        [callbackRsp setObject:@{ @"HEADERS_RECEIVED" : @2  } forKey:@"readyState"];
-                        [callbackRsp setObject:[NSNumber numberWithInteger:httpResponse.statusCode] forKey:@"status"];
-                        [callbackRsp setObject:httpResponse.allHeaderFields forKey:@"headers"];
-                        statusText = [WXStreamModule getStatusText:httpResponse.statusCode];
-                        [callbackRsp setObject:statusText forKey:@"statusText"];
-                        [callbackRsp setObject:[NSNumber numberWithInteger:received] forKey:@"length"];
-                         progressCallback(callbackRsp, TRUE);
-                    }
-                    
-                } withReceiveData:^(NSData *data) {
-                    [callbackRsp setObject:@{ @"LOADING" : @3 } forKey:@"readyState"];
-                    received += [data length];
-                    [callbackRsp setObject:[NSNumber numberWithInteger:received] forKey:@"length"];
-                     progressCallback(callbackRsp, TRUE);
-                    
-                } withCompeletion:^(NSData *totalData, NSError *error) {
-                    
-                    [callbackRsp removeObjectForKey:@"readyState"];
-                    [callbackRsp removeObjectForKey:@"length"];
-                    [callbackRsp removeObjectForKey:@"keepalive"];
-                    [callbackRsp setObject:httpResponse.statusCode >= 200 && httpResponse.statusCode <= 299 ? @true : @false forKey:@"ok"];
-                    if (error) {
-                        //error
-                        [callbackRsp setObject:@(-1) forKey:@"status"];
-                        [callbackRsp setObject:[NSString stringWithFormat:@"%@(%ld)",[error localizedDescription], (long)[error code]] forKey:@"data"];
-                        
-                        switch ([error code]) {
-                            case -1000:
-                            case -1002:
-                            case -1003:
-                                statusText = @"ERR_INVALID_REQUEST";
-                                break;
-                            default:
-                                break;
-                        }
-                        [callbackRsp setObject:statusText forKey:@"statusText"];
-                        
-                    }else {
-                        // no error
-                        NSString *responseData = [self stringfromData:totalData encode:respEncode];
-                        if ([type isEqualToString:@"json"] || [type isEqualToString:@"jsonp"]) {
-                            if ([type isEqualToString:@"jsonp"]) {
-                                NSUInteger start = [responseData rangeOfString:@"("].location + 1 ;
-                                NSUInteger end = [responseData rangeOfString:@")" options:NSBackwardsSearch].location;
-                                if (end < [responseData length] && end > start) {
-                                    responseData = [responseData substringWithRange:NSMakeRange(start, end-start)];
-                                }
-                            }
-                            id jsonObj = [self JSONObjFromData:[responseData dataUsingEncoding:NSUTF8StringEncoding]];
-                            if (jsonObj) {
-                                [callbackRsp setObject:jsonObj forKey:@"data"];
-                            }
-                            
-                        } else {
-                            if (responseData) {
-                                [callbackRsp setObject:responseData forKey:@"data"];
-                            }
-                        }
-                    }
-                    callback(callbackRsp);
-                }];
+    loader.onResponseReceived = ^(const WXResourceResponse *response) {
+        httpResponse = (NSHTTPURLResponse*)response;
+        if (weakSelf) {
+            [callbackRsp setObject:@{ @"HEADERS_RECEIVED" : @2  } forKey:@"readyState"];
+            [callbackRsp setObject:[NSNumber numberWithInteger:httpResponse.statusCode] forKey:@"status"];
+            [callbackRsp setObject:httpResponse.allHeaderFields forKey:@"headers"];
+            statusText = [WXStreamModule getStatusText:httpResponse.statusCode];
+            [callbackRsp setObject:statusText forKey:@"statusText"];
+            [callbackRsp setObject:[NSNumber numberWithInteger:received] forKey:@"length"];
+            progressCallback(callbackRsp, TRUE);
+        }
+    };
+    
+    loader.onDataReceived = ^(NSData *data) {
+        [callbackRsp setObject:@{ @"LOADING" : @3 } forKey:@"readyState"];
+        received += [data length];
+        [callbackRsp setObject:[NSNumber numberWithInteger:received] forKey:@"length"];
+        progressCallback(callbackRsp, TRUE);
+    };
+    
+    loader.onFinished = ^(const WXResourceResponse * response, NSData *data) {
+        [callbackRsp removeObjectForKey:@"readyState"];
+        [callbackRsp removeObjectForKey:@"length"];
+        [callbackRsp removeObjectForKey:@"keepalive"];
+        [callbackRsp setObject:httpResponse.statusCode >= 200 && httpResponse.statusCode <= 299 ? @true : @false forKey:@"ok"];
+    
+        NSString *responseData = [self stringfromData:data encode:httpResponse.textEncodingName];
+        if ([type isEqualToString:@"json"] || [type isEqualToString:@"jsonp"]) {
+            if ([type isEqualToString:@"jsonp"]) {
+                NSUInteger start = [responseData rangeOfString:@"("].location + 1 ;
+                NSUInteger end = [responseData rangeOfString:@")" options:NSBackwardsSearch].location;
+                if (end < [responseData length] && end > start) {
+                    responseData = [responseData substringWithRange:NSMakeRange(start, end-start)];
+                }
+            }
+            id jsonObj = [self JSONObjFromData:[responseData dataUsingEncoding:NSUTF8StringEncoding]];
+            if (jsonObj) {
+                [callbackRsp setObject:jsonObj forKey:@"data"];
+            }
+            
+        } else {
+            if (responseData) {
+                [callbackRsp setObject:responseData forKey:@"data"];
+            }
+        }
+        
+        callback(callbackRsp);
+    };
+    
+    loader.onFailed = ^(NSError *error) {
+        [callbackRsp removeObjectForKey:@"readyState"];
+        [callbackRsp removeObjectForKey:@"length"];
+        [callbackRsp removeObjectForKey:@"keepalive"];
+        [callbackRsp setObject:@(-1) forKey:@"status"];
+        [callbackRsp setObject:[NSString stringWithFormat:@"%@(%ld)",[error localizedDescription], (long)[error code]] forKey:@"data"];
+        
+        switch ([error code]) {
+            case -1000:
+            case -1002:
+            case -1003:
+                statusText = @"ERR_INVALID_REQUEST";
+                break;
+            default:
+                break;
+        }
+        [callbackRsp setObject:statusText forKey:@"statusText"];
+    };
+    
+    [loader start];
 }
 
 - (NSString*)stringfromData:(NSData *)data encode:(NSString *)encoding
@@ -340,4 +326,40 @@ WX_EXPORT_METHOD(@selector(fetch:callback:progressCallback:))
     return @"Unknown";
 }
 
+#pragma mark - Deprecated
+
+- (void)sendHttp:(NSDictionary*)param callback:(WXModuleCallback)callback
+{
+    NSString* method = [param objectForKey:@"method"];
+    NSString* urlStr = [param objectForKey:@"url"];
+    NSDictionary* headers = [param objectForKey:@"header"];
+    NSString* body = [param objectForKey:@"body"];
+    
+    NSURL *url = [NSURL URLWithString:urlStr];
+    
+    //TODO:referrer
+    WXResourceRequest *request = [WXResourceRequest requestWithURL:url resourceType:WXResourceTypeOthers referrer:nil cachePolicy:NSURLRequestUseProtocolCachePolicy];
+    request.HTTPMethod = method;
+    request.timeoutInterval = 60.0;
+    request.userAgent = [WXUtility userAgent];
+    
+    for (NSString *key in headers) {
+        NSString *value = [headers objectForKey:key];
+        [request setValue:value forHTTPHeaderField:key];
+    }
+    [request setHTTPBody:[body dataUsingEncoding:NSUTF8StringEncoding]];
+    
+    WXResourceLoader *loader = [[WXResourceLoader alloc] initWithRequest:request];
+    loader.onFinished = ^(const WXResourceResponse * response, NSData *data) {
+        NSString* responseData = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
+        callback(responseData);
+    };
+    
+    loader.onFailed = ^(NSError *error) {
+        callback(nil);
+    };
+
+    [loader start];
+}
+
 @end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Module/WXWebSocketModule.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Module/WXWebSocketModule.h b/ios/sdk/WeexSDK/Sources/Module/WXWebSocketModule.h
new file mode 100644
index 0000000..12fb84c
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Module/WXWebSocketModule.h
@@ -0,0 +1,15 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+#import <Foundation/Foundation.h>
+#import "WXModuleProtocol.h"
+#import "SRWebSocket.h"
+
+@interface WXWebSocketModule : NSObject <WXModuleProtocol>
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Module/WXWebSocketModule.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Module/WXWebSocketModule.m b/ios/sdk/WeexSDK/Sources/Module/WXWebSocketModule.m
new file mode 100644
index 0000000..ae2e158
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Module/WXWebSocketModule.m
@@ -0,0 +1,137 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+#import "WXWebSocketModule.h"
+#import "WXUtility.h"
+#import "WXWebSocketHandler.h"
+#import "WXHandlerFactory.h"
+#import "WXWebSocketLoader.h"
+#import "WXConvert.h"
+
+@interface WXWebSocketModule()
+
+@property(nonatomic,copy)WXModuleKeepAliveCallback errorCallBack;
+@property(nonatomic,copy)WXModuleKeepAliveCallback messageCallBack;
+@property(nonatomic,copy)WXModuleKeepAliveCallback openCallBack;
+@property(nonatomic,copy)WXModuleKeepAliveCallback closeCallBack;
+
+@end
+
+@implementation WXWebSocketModule
+{
+    WXWebSocketLoader *loader;
+}
+WX_EXPORT_METHOD(@selector(WebSocket:protocol:))
+WX_EXPORT_METHOD(@selector(send:))
+WX_EXPORT_METHOD(@selector(close:reason:))
+WX_EXPORT_METHOD(@selector(onerror:))
+WX_EXPORT_METHOD(@selector(onmessage:))
+WX_EXPORT_METHOD(@selector(onopen:))
+WX_EXPORT_METHOD(@selector(onclose:))
+
+@synthesize weexInstance;
+
+- (void)WebSocket:(NSString *)url protocol:(NSString *)protocol
+{
+    if(loader)
+    {
+        [loader clear];
+    }
+    loader = [[WXWebSocketLoader alloc] initWithUrl:url protocol:protocol];
+    __weak typeof(self) weakSelf = self;
+    loader.onReceiveMessage = ^(id message) {
+        if (weakSelf) {
+            NSMutableDictionary *dic = [NSMutableDictionary new];
+            if([message isKindOfClass:[NSString class]]) {
+                [dic setObject:message forKey:@"data"];
+            }
+            if (weakSelf.messageCallBack) {
+                weakSelf.messageCallBack(dic,true);;
+            }
+        }
+    };
+    loader.onOpen = ^() {
+        if (weakSelf) {
+            if (weakSelf.openCallBack) {
+                NSMutableDictionary *dict = [NSMutableDictionary new];
+                weakSelf.openCallBack(dict,true);;
+            }
+        }
+    };
+    loader.onFail = ^(NSError *error) {
+        if (weakSelf) {
+            WXLogError(@":( Websocket Failed With Error %@", error);
+            NSMutableDictionary *dict = [NSMutableDictionary new];
+            [dict setObject:error.userInfo forKey:@"data"];
+            if (weakSelf.errorCallBack) {
+                weakSelf.errorCallBack(dict, true);
+            }
+        }
+    };
+    loader.onClose = ^(NSInteger code,NSString *reason,BOOL wasClean) {
+        if (weakSelf) {
+            if (weakSelf.closeCallBack) {
+                WXLogInfo(@"Websocket colse ");
+                NSMutableDictionary * callbackRsp = [[NSMutableDictionary alloc] init];
+                [callbackRsp setObject:[NSNumber numberWithInteger:code] forKey:@"code"];
+                [callbackRsp setObject:reason forKey:@"reason"];
+                [callbackRsp setObject:wasClean?@true:@false forKey:@"wasClean"];
+                weakSelf.closeCallBack(callbackRsp,false);
+            }
+        }
+    };
+    
+    [loader open];
+}
+
+- (void)send:(NSString *)data
+{
+    [loader send:data];
+}
+
+- (void)close
+{
+    [loader close];
+}
+
+- (void)close:(NSString *)code reason:(NSString *)reason
+{
+    if(!code)
+    {
+        [loader close];
+        return;
+    }
+    [loader close:[code integerValue] reason:reason];
+}
+
+- (void)onerror:(WXModuleKeepAliveCallback)callback
+{
+    self.errorCallBack = callback;
+}
+
+- (void)onmessage:(WXModuleKeepAliveCallback)callback
+{
+    self.messageCallBack = callback;
+}
+
+- (void)onopen:(WXModuleKeepAliveCallback)callback
+{
+    self.openCallBack = callback;
+}
+
+- (void)onclose:(WXModuleKeepAliveCallback)callback
+{
+    self.closeCallBack = callback;
+}
+
+-(void)dealloc
+{
+    [loader clear];
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Monitor/WXMonitor.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Monitor/WXMonitor.h b/ios/sdk/WeexSDK/Sources/Monitor/WXMonitor.h
index c874935..076e0c7 100644
--- a/ios/sdk/WeexSDK/Sources/Monitor/WXMonitor.h
+++ b/ios/sdk/WeexSDK/Sources/Monitor/WXMonitor.h
@@ -8,6 +8,7 @@
 
 #import <Foundation/Foundation.h>
 #import "WXDefine.h"
+#import "WXSDKError.h"
 
 @class WXSDKInstance;
 
@@ -30,6 +31,7 @@ typedef enum : NSUInteger {
     WXMTJSDownload,
     WXMTJSBridge,
     WXMTNativeRender,
+    WXMTJSService,
 } WXMonitorTag;
 
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Network/WXResourceRequest.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Network/WXResourceRequest.h b/ios/sdk/WeexSDK/Sources/Network/WXResourceRequest.h
new file mode 100644
index 0000000..d8ab92a
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Network/WXResourceRequest.h
@@ -0,0 +1,35 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+#import <Foundation/Foundation.h>
+
+typedef enum : NSUInteger {
+    WXResourceTypeMainBundle,
+    WXResourceTypeServiceBundle,
+    WXResourceTypeImage,
+    WXResourceTypeFont,
+    WXResourceTypeVideo,
+    WXResourceTypeLink,
+    WXResourceTypeOthers
+} WXResourceType;
+
+
+@interface WXResourceRequest : NSMutableURLRequest
+
+@property (nonatomic, strong) id taskIdentifier;
+@property (nonatomic, assign) WXResourceType type;
+
+@property (nonatomic, strong) NSString *referrer;
+@property (nonatomic, strong) NSString *userAgent;
+
++ (instancetype)requestWithURL:(NSURL *)url
+                  resourceType:(WXResourceType)type
+                      referrer:(NSString *)referrer
+                   cachePolicy:(NSURLRequestCachePolicy)cachePolicy;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Network/WXResourceRequest.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Network/WXResourceRequest.m b/ios/sdk/WeexSDK/Sources/Network/WXResourceRequest.m
new file mode 100644
index 0000000..b161d8f
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Network/WXResourceRequest.m
@@ -0,0 +1,57 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+#import "WXResourceRequest.h"
+
+NSString * const kHTTPHeaderNameUserAgent = @"User-Agent";
+NSString * const kHTTPHeaderNameReferrer = @"Referer"; // The misspelling referer originated in the original proposal by computer "scientist" Phillip Hallam-Baker to incorporate the field into the HTTP specification. \u256e(\u256f_\u2570)\u256d
+
+@implementation WXResourceRequest
+
++ (instancetype)requestWithURL:(NSURL *)url
+                  resourceType:(WXResourceType)type
+                      referrer:(NSString *)referrer
+                   cachePolicy:(NSURLRequestCachePolicy)cachePolicy
+{
+    return [[self alloc] initWithURL:url resourceType:type referrer:referrer cachePolicy:cachePolicy];
+}
+
+- (instancetype)initWithURL:(NSURL *)url
+               resourceType:(WXResourceType)type
+                   referrer:(NSString *)referrer cachePolicy:(NSURLRequestCachePolicy)cachePolicy
+{
+    if (self = [super initWithURL:url]) {
+        self.type = type;
+        self.cachePolicy = cachePolicy;
+        [self setValue:referrer forHTTPHeaderField:kHTTPHeaderNameReferrer];
+    }
+    
+    return self;
+}
+
+- (NSString *)referrer
+{
+    return [self valueForHTTPHeaderField:kHTTPHeaderNameReferrer];
+}
+
+- (void)setReferrer:(NSString *)referrer
+{
+    [self setValue:referrer forHTTPHeaderField:kHTTPHeaderNameReferrer];
+}
+
+- (NSString *)userAgent
+{
+    return [self valueForHTTPHeaderField:kHTTPHeaderNameUserAgent];
+}
+
+- (void)setUserAgent:(NSString *)userAgent
+{
+    [self setValue:userAgent forHTTPHeaderField:kHTTPHeaderNameUserAgent];
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Network/WXResourceRequestHandler.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Network/WXResourceRequestHandler.h b/ios/sdk/WeexSDK/Sources/Network/WXResourceRequestHandler.h
new file mode 100644
index 0000000..7f5393b
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Network/WXResourceRequestHandler.h
@@ -0,0 +1,45 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+
+#import <Foundation/Foundation.h>
+#import "WXResourceRequest.h"
+#import "WXResourceResponse.h"
+
+@protocol WXResourceRequestDelegate <NSObject>
+
+// Periodically informs the delegate of the progress of sending content to the server.
+- (void)request:(WXResourceRequest *)request didSendData:(unsigned long long)bytesSent totalBytesToBeSent:(unsigned long long)totalBytesToBeSent;
+
+// Tells the delegate that the request received the initial reply (headers) from the server.
+- (void)request:(WXResourceRequest *)request didReceiveResponse:(WXResourceResponse *)response;
+
+// Tells the delegate that the request has received some of the expected data.
+- (void)request:(WXResourceRequest *)request didReceiveData:(NSData *)data;
+
+// Tells the delegate that the request finished transferring data.
+- (void)requestDidFinishLoading:(WXResourceRequest *)request;
+
+// Tells the delegate that the request failed to load successfully.
+- (void)request:(WXResourceRequest *)request didFailWithError:(NSError *)error;
+
+@end
+
+@protocol WXResourceRequestHandler <NSObject>
+
+// Send a resource request with a delegate
+- (void)sendRequest:(WXResourceRequest *)request withDelegate:(id<WXResourceRequestDelegate>)delegate;
+
+@optional
+
+// Cancel the ongoing request
+- (void)cancelRequest:(WXResourceRequest *)request;
+
+@end
+
+

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Network/WXResourceRequestHandlerDefaultImpl.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Network/WXResourceRequestHandlerDefaultImpl.h b/ios/sdk/WeexSDK/Sources/Network/WXResourceRequestHandlerDefaultImpl.h
new file mode 100644
index 0000000..d68ca8c
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Network/WXResourceRequestHandlerDefaultImpl.h
@@ -0,0 +1,15 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+
+#import <Foundation/Foundation.h>
+#import "WXResourceRequestHandler.h"
+
+@interface WXResourceRequestHandlerDefaultImpl : NSObject <WXResourceRequestHandler>
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Network/WXResourceRequestHandlerDefaultImpl.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Network/WXResourceRequestHandlerDefaultImpl.m b/ios/sdk/WeexSDK/Sources/Network/WXResourceRequestHandlerDefaultImpl.m
new file mode 100644
index 0000000..211471f
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Network/WXResourceRequestHandlerDefaultImpl.m
@@ -0,0 +1,90 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+
+#import "WXResourceRequestHandlerDefaultImpl.h"
+#import "WXThreadSafeMutableDictionary.h"
+#import "WXAppConfiguration.h"
+
+@interface WXResourceRequestHandlerDefaultImpl () <NSURLSessionDataDelegate>
+
+@end
+
+@implementation WXResourceRequestHandlerDefaultImpl
+{
+    NSURLSession *_session;
+    WXThreadSafeMutableDictionary<NSURLSessionDataTask *, id<WXResourceRequestDelegate>> *_delegates;
+}
+
+#pragma mark - WXResourceRequestHandler
+
+- (void)sendRequest:(WXResourceRequest *)request withDelegate:(id<WXResourceRequestDelegate>)delegate
+{
+    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 = [WXThreadSafeMutableDictionary 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];
+    [delegate requestDidFinishLoading:(WXResourceRequest *)task.originalRequest];
+    [_delegates removeObjectForKey:task];
+}
+
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Network/WXResourceResponse.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Network/WXResourceResponse.h b/ios/sdk/WeexSDK/Sources/Network/WXResourceResponse.h
new file mode 100644
index 0000000..06ec6bd
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Network/WXResourceResponse.h
@@ -0,0 +1,14 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+
+#import <Foundation/Foundation.h>
+
+@interface WXResourceResponse : NSURLResponse
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Network/WXResourceResponse.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Network/WXResourceResponse.m b/ios/sdk/WeexSDK/Sources/Network/WXResourceResponse.m
new file mode 100644
index 0000000..b7b5e59
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Network/WXResourceResponse.m
@@ -0,0 +1,14 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+
+#import "WXResourceResponse.h"
+
+@implementation WXResourceResponse
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Protocol/WXBridgeProtocol.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Protocol/WXBridgeProtocol.h b/ios/sdk/WeexSDK/Sources/Protocol/WXBridgeProtocol.h
index 035b5b7..fd19706 100644
--- a/ios/sdk/WeexSDK/Sources/Protocol/WXBridgeProtocol.h
+++ b/ios/sdk/WeexSDK/Sources/Protocol/WXBridgeProtocol.h
@@ -8,9 +8,10 @@
 
 #import <JavaScriptCore/JavaScriptCore.h>
 
-typedef NSInteger (^WXJSCallNative)(NSString *instance, NSArray *tasks, NSString *callback);
-typedef NSInteger (^WXJSCallAddElement)(NSString *instanceId,  NSString *parentRef, NSDictionary *elementData, NSInteger index);
-
+typedef NSInteger(^WXJSCallNative)(NSString *instance, NSArray *tasks, NSString *callback);
+typedef NSInteger(^WXJSCallAddElement)(NSString *instanceId,  NSString *parentRef, NSDictionary *elementData, NSInteger index);
+typedef NSInvocation *(^WXJSCallNativeModule)(NSString *instanceId, NSString *moduleName, NSString *methodName, NSArray *args, NSDictionary *options);
+typedef void (^WXJSCallNativeComponent)(NSString *instanceId, NSString *componentRef, NSString *methodName, NSArray *args, NSDictionary *options);
 
 @protocol WXBridgeProtocol <NSObject>
 
@@ -23,6 +24,12 @@ typedef NSInteger (^WXJSCallAddElement)(NSString *instanceId,  NSString *parentR
 - (void)executeJSFramework:(NSString *)frameworkScript;
 
 /**
+ * Executes the js code in javascript engine
+ * You can do some setup in this method
+ */
+- (void)executeJavascript:(NSString *)script;
+
+/**
  * Executes global js method with specific arguments
  */
 - (JSValue *)callJSMethod:(NSString *)method args:(NSArray*)args;
@@ -40,13 +47,24 @@ typedef NSInteger (^WXJSCallAddElement)(NSString *instanceId,  NSString *parentR
 @optional
 
 /**
+ * Called when garbage collection is wanted by sdk.
+ */
+- (void)garbageCollect;
+
+/**
  * Register callback when addElement tasks occur
  */
 - (void)registerCallAddElement:(WXJSCallAddElement)callAddElement;
 
 /**
- * Called when garbage collection is wanted by sdk.
+ * Register callback for global js function `callNativeModule`
  */
-- (void)garbageCollect;
+- (void)registerCallNativeModule:(WXJSCallNativeModule)callNativeModuleBlock;
+
+/**
+ * Register callback for global js function `callNativeComponent`
+ */
+- (void)registerCallNativeComponent:(WXJSCallNativeComponent)callNativeComponentBlock;
+
 
 @end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Protocol/WXModuleProtocol.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Protocol/WXModuleProtocol.h b/ios/sdk/WeexSDK/Sources/Protocol/WXModuleProtocol.h
index 327d6d7..1e2528c 100644
--- a/ios/sdk/WeexSDK/Sources/Protocol/WXModuleProtocol.h
+++ b/ios/sdk/WeexSDK/Sources/Protocol/WXModuleProtocol.h
@@ -24,7 +24,6 @@
  * @discussion callback data to js, the id of callback function will be removed to save memory.
  */
 typedef void (^WXModuleCallback)(id result);
-typedef void (^WXModuleKeepAliveCallback)(id result, BOOL keepAlive);
 
 /**
  * @abstract the module callback , result can be string or dictionary.

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Protocol/WXNavigationProtocol.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Protocol/WXNavigationProtocol.h b/ios/sdk/WeexSDK/Sources/Protocol/WXNavigationProtocol.h
index c8f76b4..80cf2ae 100644
--- a/ios/sdk/WeexSDK/Sources/Protocol/WXNavigationProtocol.h
+++ b/ios/sdk/WeexSDK/Sources/Protocol/WXNavigationProtocol.h
@@ -119,18 +119,39 @@ typedef void (^WXNavigationResultBlock)(NSString *code, NSDictionary * responseD
                         completion:(WXNavigationResultBlock)block
                      withContainer:(UIViewController *)container;
 
+    
+@optional
+    
 /**
- * @abstract Pops all the view controllers on the stack except the root view controller.
+ * @abstract open the resource at the specified URL which supports many common schemes, including the http, https, tel and mailto schemes.
  *
  * @param param The data which is passed to the implementation of the protocol.
  *
- * @param block A block called once the action is completed.
+ * @param block A block called once the action is completed successfully.
+ *
+ * @param block A block called once the action failed to be completed.
  *
  * @param container The target controller.
  *
  */
-- (void)popToRootViewControllerWithParam:(NSDictionary *)param
-                              completion:(WXNavigationResultBlock)block
-                           withContainer:(UIViewController *)container;
+- (void)open:(NSDictionary *)param success:(WXModuleCallback)success
+                                   failure:(WXModuleCallback)failure
+                             withContainer:(UIViewController *)container;
 
+
+/**
+  * @abstract close the current weex page
+  *
+  * @param param The data which is passed to the implementation of the protocol.
+  *
+  * @param block A block called once the action is completed successfully.
+  *
+  * @param block A block called once the action failed to be completed.
+  *
+  * @param container The target controller.
+  *
+  */
+- (void)close:(NSDictionary *)param success:(WXModuleCallback)success
+                                   failure:(WXModuleCallback)failure
+                             withContainer:(UIViewController *)container;
 @end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Protocol/WXNetworkProtocol.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Protocol/WXNetworkProtocol.h b/ios/sdk/WeexSDK/Sources/Protocol/WXNetworkProtocol.h
index ced6ce7..0f0f335 100644
--- a/ios/sdk/WeexSDK/Sources/Protocol/WXNetworkProtocol.h
+++ b/ios/sdk/WeexSDK/Sources/Protocol/WXNetworkProtocol.h
@@ -9,6 +9,7 @@
 #import <Foundation/Foundation.h>
 #import "WXModuleProtocol.h"
 
+__attribute__ ((deprecated("Use WXResourceRequestHandler instead")))
 @protocol WXNetworkProtocol <NSObject>
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Protocol/WXURLRewriteProtocol.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Protocol/WXURLRewriteProtocol.h b/ios/sdk/WeexSDK/Sources/Protocol/WXURLRewriteProtocol.h
index a48f8a0..9f065ad 100644
--- a/ios/sdk/WeexSDK/Sources/Protocol/WXURLRewriteProtocol.h
+++ b/ios/sdk/WeexSDK/Sources/Protocol/WXURLRewriteProtocol.h
@@ -7,18 +7,10 @@
  */
 
 #import <Foundation/Foundation.h>
+#import "WXResourceRequest.h"
 
 @class WXSDKInstance;
 
-typedef enum : NSUInteger {
-    WXResourceTypeBundle,
-    WXResourceTypeImage,
-    WXResourceTypeFont,
-    WXResourceTypeVideo,
-    WXResourceTypeLink,
-    WXResourceTypeOthers
-} WXResourceType;
-
 #define WX_REWRITE_URL(url, resourceType, instance, newUrl)\
 do {\
     (*newUrl) = nil;\

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Utility/WXConvert.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.h b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.h
index c502229..3005c82 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.h
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.h
@@ -24,7 +24,8 @@
  *  750px Adaptive
  */
 typedef CGFloat WXPixelType;
-+ (WXPixelType)WXPixelType:(id)value;
+// @prameter scaleFactor: please use weexInstance's pixelScaleFactor property
++ (WXPixelType)WXPixelType:(id)value scaleFactor:(CGFloat)scaleFactor;
 
 + (css_flex_direction_t)css_flex_direction_t:(id)value;
 + (css_align_t)css_align_t:(id)value;
@@ -44,15 +45,32 @@ typedef BOOL WXClipType;
 + (WXPositionType)WXPositionType:(id)value;
 
 + (WXTextStyle)WXTextStyle:(id)value;
-+ (WXTextWeight)WXTextWeight:(id)value;
+/**
+ * @abstract UIFontWeightRegular ,UIFontWeightBold,etc are not support by the system which is less than 8.2. weex sdk set the float value.
+ *
+ * @param value, support normal,blod,100,200,300,400,500,600,700,800,900
+ *
+ * @return A float value.
+ *
+ */
++ (CGFloat)WXTextWeight:(id)value;
 + (WXTextDecoration)WXTextDecoration:(id)value;
 + (NSTextAlignment)NSTextAlignment:(id)value;
 
 + (WXScrollDirection)WXScrollDirection:(id)value;
++ (UITableViewRowAnimation)UITableViewRowAnimation:(id)value;
 
 + (UIViewAnimationOptions)UIViewAnimationTimingFunction:(id)value;
 + (CAMediaTimingFunction *)CAMediaTimingFunction:(id)value;
 
 + (WXVisibility)WXVisibility:(id)value;
 
++ (WXGradientType)gradientType:(id)value;
+
+@end
+
+@interface WXConvert (Deprecated)
+
++ (WXPixelType)WXPixelType:(id)value DEPRECATED_MSG_ATTRIBUTE("Use [WXConvert WXPixelType:scaleFactor:] instead");
+
 @end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m
index ecb2fea..cc76c5e 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m
@@ -70,11 +70,11 @@ WX_NUMBER_CONVERT(NSUInteger, unsignedIntegerValue)
     return nil;
 }
 
-+ (WXPixelType)WXPixelType:(id)value
++ (WXPixelType)WXPixelType:(id)value scaleFactor:(CGFloat)scaleFactor
 {
     CGFloat pixel = [self CGFloat:value];
     
-    return pixel * WXScreenResizeRadio();
+    return pixel * scaleFactor;
 }
 
 #pragma mark CSS Layout
@@ -478,16 +478,35 @@ WX_NUMBER_CONVERT(NSUInteger, unsignedIntegerValue)
     return WXTextStyleNormal;
 }
 
-+ (WXTextWeight)WXTextWeight:(id)value
++ (CGFloat)WXTextWeight:(id)value
 {
     if([value isKindOfClass:[NSString class]]){
         NSString *string = (NSString *)value;
         if ([string isEqualToString:@"normal"])
-            return WXTextWeightNormal;
+            return WX_SYS_VERSION_LESS_THAN(@"8.2")?0:UIFontWeightRegular;
         else if ([string isEqualToString:@"bold"])
-            return WXTextWeightBold;
+            return WX_SYS_VERSION_LESS_THAN(@"8.2")?0.4:UIFontWeightBold;
+        else if ([string isEqualToString:@"100"])
+            return WX_SYS_VERSION_LESS_THAN(@"8.2")?-0.8:UIFontWeightUltraLight;
+        else if ([string isEqualToString:@"200"])
+            return WX_SYS_VERSION_LESS_THAN(@"8.2")?-0.6:UIFontWeightThin;
+        else if ([string isEqualToString:@"300"])
+            return WX_SYS_VERSION_LESS_THAN(@"8.2")?-0.4:UIFontWeightLight;
+        else if ([string isEqualToString:@"400"])
+            return WX_SYS_VERSION_LESS_THAN(@"8.2")?0:UIFontWeightRegular;
+        else if ([string isEqualToString:@"500"])
+            return WX_SYS_VERSION_LESS_THAN(@"8.2")?0.23:UIFontWeightMedium;
+        else if ([string isEqualToString:@"600"])
+            return WX_SYS_VERSION_LESS_THAN(@"8.2")?0.3:UIFontWeightSemibold;
+        else if ([string isEqualToString:@"700"])
+            return WX_SYS_VERSION_LESS_THAN(@"8.2")?0.4:UIFontWeightBold;
+        else if ([string isEqualToString:@"800"])
+            return WX_SYS_VERSION_LESS_THAN(@"8.2")?0.56:UIFontWeightHeavy;
+        else if ([string isEqualToString:@"900"])
+            return WX_SYS_VERSION_LESS_THAN(@"8.2")?0.62:UIFontWeightBlack;
+
     }
-    return WXTextWeightNormal;
+    return WX_SYS_VERSION_LESS_THAN(@"8.2")?0:UIFontWeightRegular;
 }
 
 + (WXTextDecoration)WXTextDecoration:(id)value
@@ -567,6 +586,20 @@ WX_NUMBER_CONVERT(NSUInteger, unsignedIntegerValue)
     return WXScrollDirectionVertical;
 }
 
++ (UITableViewRowAnimation)UITableViewRowAnimation:(id)value
+{
+    if ([value isKindOfClass:[NSString class]]) {
+        NSString *string = (NSString *)value;
+        if ([string isEqualToString:@"none"]) {
+            return UITableViewRowAnimationNone;
+        } else if ([string isEqualToString:@"default"]) {
+            return UITableViewRowAnimationFade;
+        }
+    }
+    
+    return UITableViewRowAnimationNone;
+}
+
 #pragma mark Animation
 
 + (UIViewAnimationOptions)UIViewAnimationTimingFunction:(id)value
@@ -636,4 +669,46 @@ WX_NUMBER_CONVERT(NSUInteger, unsignedIntegerValue)
     return  WXVisibilityShow;
 }
 
+#pragma mark Gradient Color
+
++ (WXGradientType)gradientType:(id)value
+{
+    WXGradientType type = WXGradientTypeToRight;
+    
+    if ([value isKindOfClass:[NSString class]]) {
+        NSString *string = (NSString *)value;
+        
+        if ([string isEqualToString:@"totop"]) {
+            type = WXGradientTypeToTop;
+        }
+        else if ([string isEqualToString:@"tobottom"]) {
+            type = WXGradientTypeToBottom;
+        }
+        else if ([string isEqualToString:@"toleft"]) {
+            type = WXGradientTypeToLeft;
+        }
+        if ([string isEqualToString:@"toright"]) {
+            type = WXGradientTypeToRight;
+        }
+        else if ([string isEqualToString:@"totopleft"]) {
+            type = WXGradientTypeToTopleft;
+        }
+        else if ([string isEqualToString:@"tobottomright"]) {
+            type = WXGradientTypeToBottomright;
+        }
+    }
+    return type;
+}
+
+@end
+
+@implementation WXConvert (Deprecated)
+
++ (WXPixelType)WXPixelType:(id)value
+{
+    CGFloat pixel = [self CGFloat:value];
+    
+    return pixel * WXScreenResizeRadio();
+}
+
 @end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Utility/WXDefine.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXDefine.h b/ios/sdk/WeexSDK/Sources/Utility/WXDefine.h
index 9d39a48..d743d53 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXDefine.h
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXDefine.h
@@ -9,7 +9,7 @@
 #ifndef __WX_DEFINE_H__
 #define __WX_DEFINE_H__
 
-#define WX_SDK_VERSION @"0.9.4"
+#define WX_SDK_VERSION @"0.9.5"
 
 #if defined(__cplusplus)
 #define WX_EXTERN extern "C" __attribute__((visibility("default")))
@@ -34,7 +34,7 @@
 
 #define WX_SDK_ROOT_REF     @"_root"
 
-#define WX_TEXT_FONT_SIZE   (32.0 * WXScreenResizeRadio())
+#define WX_TEXT_FONT_SIZE   (32.0 * self.weexInstance.pixelScaleFactor)
 
 #define WX_UPDATE_CONFIG(prefix, name, configs) \
 NSString *selStr = [NSString stringWithFormat:@"%@_%@", prefix, name];\
@@ -62,6 +62,10 @@ parts = [parts subarrayWithRange:(NSRange){0, parts.count - 1}];\
 
 #define WX_ERROR_DOMAIN @"WXErrorDomain"
 
+#define WX_APPLICATION_WILL_RESIGN_ACTIVE @"WXApplicationWillResignActiveEvent"
+
+#define WX_APPLICATION_DID_BECOME_ACTIVE @"WXApplicationDidBecomeActiveEvent"
+
 #define WX_INSTANCE_NOTIFICATION_UPDATE_STATE @"WXInstUpdateState"
 
 #define WX_COMPONENT_THREAD_NAME @"com.taobao.weex.component"
@@ -70,16 +74,25 @@ parts = [parts subarrayWithRange:(NSRange){0, parts.count - 1}];\
 
 #define WX_FONT_DOWNLOAD_DIR [[WXUtility cacheDirectory] stringByAppendingPathComponent:[NSString stringWithFormat:@"wxdownload"]]
 
+#define WX_EXPORT_METHOD_INTERNAL(method, token) \
++ (NSString *)WX_CONCAT_WRAPPER(token, __LINE__) { \
+    return NSStringFromSelector(method); \
+}
+
+#define WX_MODULE_EVENT_FIRE_NOTIFICATION  @"WX_MODULE_EVENT_FIRE_NOTIFICATION"
+
 /**
  *  @abstract export public method
  */
+#define WX_EXPORT_METHOD(method) WX_EXPORT_METHOD_INTERNAL(method,wx_export_method_)
 
-#define WX_EXPORT_METHOD(method) \
-+ (NSString *)WX_CONCAT_WRAPPER(wx_export_method_, __LINE__) { \
-return NSStringFromSelector(method); \
-}
+/**
+ *  @abstract export public method, support sync return value
+ *  @warning the method can only be called on js thread
+ */
+#define WX_EXPORT_METHOD_SYNC(method) WX_EXPORT_METHOD_INTERNAL(method,wx_export_method_sync_)
 
-/** extern "C" makes a function-name in C++ have 'C' linkage (compiler does not mangle the name) 
+/** extern "C" makes a function-name in C++ have 'C' linkage (compiler does not mangle the name)
  * so that client C code can link to (i.e use) your function using a 'C' compatible header file that contains just the declaration of your function.
  *  http://stackoverflow.com/questions/1041866/in-c-source-what-is-the-effect-of-extern-c
  */

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Utility/WXType.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXType.h b/ios/sdk/WeexSDK/Sources/Utility/WXType.h
index 8043cc2..e00878d 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXType.h
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXType.h
@@ -20,11 +20,6 @@ typedef NS_ENUM(NSUInteger, WXTextStyle) {
     WXTextStyleItalic
 };
 
-typedef NS_ENUM(NSUInteger, WXTextWeight) {
-    WXTextWeightNormal = 0,
-    WXTextWeightBold,
-};
-
 typedef NS_ENUM(NSInteger, WXTextDecoration) {
     WXTextDecorationNone = 0,
     WXTextDecorationUnderline,
@@ -63,3 +58,11 @@ typedef NS_ENUM(NSInteger, WXPositionType) {
     WXPositionTypeFixed
 };
 
+typedef NS_ENUM(NSInteger, WXGradientType) {
+    WXGradientTypeToTop = 0,
+    WXGradientTypeToBottom,
+    WXGradientTypeToLeft,
+    WXGradientTypeToRight,
+    WXGradientTypeToTopleft,
+    WXGradientTypeToBottomright,
+};