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:41:02 UTC

[13/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/Bridge/JSValue+Weex.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.h b/ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.h
new file mode 100644
index 0000000..3270a95
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.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 <JavaScriptCore/JavaScriptCore.h>
+
+@interface JSValue (Weex)
+
++ (JSValue *)wx_valueWithReturnValueFromInvocation:(NSInvocation *)invocation inContext:(JSContext *)context;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.m b/ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.m
new file mode 100644
index 0000000..3bc3dda
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Bridge/JSValue+Weex.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 "JSValue+Weex.h"
+#import <objc/runtime.h>
+
+@implementation JSValue (Weex)
+
++ (JSValue *)wx_valueWithReturnValueFromInvocation:(NSInvocation *)invocation inContext:(JSContext *)context
+{
+    if (!invocation || !context) {
+        return nil;
+    }
+    
+    const char * returnType = [invocation.methodSignature methodReturnType];
+    
+    JSValue *returnValue;
+    switch (returnType[0] == _C_CONST ? returnType[1] : returnType[0]) {
+        case _C_VOID: {
+            // 1.void
+            returnValue = [JSValue valueWithUndefinedInContext:context];
+            break;
+        }
+        
+        case _C_ID: {
+            // 2.id
+            void *value;
+            [invocation getReturnValue:&value];
+            id object = (__bridge id)value;
+        
+            returnValue = [JSValue valueWithObject:[object copy] inContext:context];
+            break;
+        }
+        
+#define WX_JS_VALUE_RET_CASE(typeString, type) \
+        case typeString: {                      \
+            type value;                         \
+            [invocation getReturnValue:&value];  \
+            returnValue = [JSValue valueWithObject:@(value) inContext:context]; \
+            break; \
+        }
+        // 3.number
+        WX_JS_VALUE_RET_CASE(_C_CHR, char)
+        WX_JS_VALUE_RET_CASE(_C_UCHR, unsigned char)
+        WX_JS_VALUE_RET_CASE(_C_SHT, short)
+        WX_JS_VALUE_RET_CASE(_C_USHT, unsigned short)
+        WX_JS_VALUE_RET_CASE(_C_INT, int)
+        WX_JS_VALUE_RET_CASE(_C_UINT, unsigned int)
+        WX_JS_VALUE_RET_CASE(_C_LNG, long)
+        WX_JS_VALUE_RET_CASE(_C_ULNG, unsigned long)
+        WX_JS_VALUE_RET_CASE(_C_LNG_LNG, long long)
+        WX_JS_VALUE_RET_CASE(_C_ULNG_LNG, unsigned long long)
+        WX_JS_VALUE_RET_CASE(_C_FLT, float)
+        WX_JS_VALUE_RET_CASE(_C_DBL, double)
+        WX_JS_VALUE_RET_CASE(_C_BOOL, BOOL)
+            
+        case _C_STRUCT_B: {
+            NSString *typeString = [NSString stringWithUTF8String:returnType];
+            
+#define WX_JS_VALUE_RET_STRUCT(_type, _methodName)                             \
+            if ([typeString rangeOfString:@#_type].location != NSNotFound) {   \
+                _type value;                                                   \
+                [invocation getReturnValue:&value];                            \
+                returnValue = [JSValue _methodName:value inContext:context]; \
+                break;                                                         \
+            }
+            // 4.struct
+            WX_JS_VALUE_RET_STRUCT(CGRect, valueWithRect)
+            WX_JS_VALUE_RET_STRUCT(CGPoint, valueWithPoint)
+            WX_JS_VALUE_RET_STRUCT(CGSize, valueWithSize)
+            WX_JS_VALUE_RET_STRUCT(NSRange, valueWithRange)
+            
+        }
+        case _C_CHARPTR:
+        case _C_PTR:
+        case _C_CLASS: {
+            returnValue = [JSValue valueWithUndefinedInContext:context];
+            break;
+        }
+    }
+    
+    return returnValue;
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.h b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.h
index 4388bdf..1f4ee27 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.h
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.h
@@ -8,7 +8,7 @@
 
 #import <Foundation/Foundation.h>
 
-@class WXBridgeMethod;
+@class WXCallJSMethod;
 @class WXSDKInstance;
 
 @interface WXBridgeContext : NSObject
@@ -62,7 +62,7 @@
  *  Execute JS Method
  *  @param method    :   object of bridge method
  **/
-- (void)executeJsMethod:(WXBridgeMethod *)method;
+- (void)executeJsMethod:(WXCallJSMethod *)method;
 /**
  *  Register Modules Method
  *  @param modules   :   module list
@@ -70,6 +70,13 @@
 - (void)registerModules:(NSDictionary *)modules;
 
 /**
+ *  Execute JS Service
+ *  @param method    :   JS services name
+ *  @param method    :   JS services script
+ **/
+- (void)executeJsService:(NSString *)script withName: (NSString *)name;
+
+/**
  *  Register Components Method
  *  @param components:   component list
  **/

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
index 79e22f3..9eae7de 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
@@ -12,7 +12,6 @@
 #import "WXDebugLoggerBridge.h"
 #import "WXLog.h"
 #import "WXUtility.h"
-#import "WXBridgeMethod.h"
 #import "WXModuleFactory.h"
 #import "WXModuleProtocol.h"
 #import "WXUtility.h"
@@ -21,11 +20,14 @@
 #import "WXAssert.h"
 #import "WXSDKManager.h"
 #import "WXDebugTool.h"
-#import "WXModuleManager.h"
 #import "WXSDKInstance_private.h"
 #import "WXThreadSafeMutableArray.h"
 #import "WXAppConfiguration.h"
 #import "WXInvocationConfig.h"
+#import "WXComponentMethod.h"
+#import "WXModuleMethod.h"
+#import "WXCallJSMethod.h"
+#import "WXSDKInstance_private.h"
 
 #define SuppressPerformSelectorLeakWarning(Stuff) \
 do { \
@@ -48,6 +50,8 @@ _Pragma("clang diagnostic pop") \
 @property (nonatomic) BOOL frameworkLoadFinished;
 //store some methods temporarily before JSFramework is loaded
 @property (nonatomic, strong) NSMutableArray *methodQueue;
+// store template service
+@property (nonatomic, strong) NSMutableArray *jsServiceQueue;
 
 @end
 
@@ -59,6 +63,7 @@ _Pragma("clang diagnostic pop") \
     if (self) {
         _methodQueue = [NSMutableArray new];
         _frameworkLoadFinished = NO;
+        _jsServiceQueue = [NSMutableArray new];
     }
     return self;
 }
@@ -80,12 +85,20 @@ _Pragma("clang diagnostic pop") \
     }
     
     _jsBridge = _debugJS ? [NSClassFromString(@"WXDebugger") alloc] : [[WXJSCoreBridge alloc] init];
-     __weak typeof(self) weakSelf = self;
+    
+    [self registerGlobalFuntions];
+    
+    return _jsBridge;
+}
+
+- (void)registerGlobalFuntions
+{
+    __weak typeof(self) weakSelf = self;
     [_jsBridge registerCallNative:^NSInteger(NSString *instance, NSArray *tasks, NSString *callback) {
         return [weakSelf invokeNative:instance tasks:tasks callback:callback];
     }];
     [_jsBridge registerCallAddElement:^NSInteger(NSString *instanceId, NSString *parentRef, NSDictionary *elementData, NSInteger index) {
-
+        
         // Temporary here , in order to improve performance, will be refactored next version.
         WXSDKInstance *instance = [WXSDKManager instanceForID:instanceId];
         
@@ -106,7 +119,24 @@ _Pragma("clang diagnostic pop") \
         return 0;
     }];
     
-    return _jsBridge;
+    [_jsBridge registerCallNativeModule:^NSInvocation*(NSString *instanceId, NSString *moduleName, NSString *methodName, NSArray *arguments, NSDictionary *options) {
+        
+        WXSDKInstance *instance = [WXSDKManager instanceForID:instanceId];
+        
+        if (!instance) {
+            WXLogInfo(@"instance not found for callNativeModule:%@.%@, maybe already destroyed", moduleName, methodName);
+            return nil;
+        }
+        
+        WXModuleMethod *method = [[WXModuleMethod alloc] initWithModuleName:moduleName methodName:methodName arguments:arguments instance:instance];
+        return [method invoke];
+    }];
+    
+    [_jsBridge registerCallNativeComponent:^void(NSString *instanceId, NSString *componentRef, NSString *methodName, NSArray *args, NSDictionary *options) {
+        WXSDKInstance *instance = [WXSDKManager instanceForID:instanceId];
+        WXComponentMethod *method = [[WXComponentMethod alloc] initWithComponentRef:componentRef methodName:methodName arguments:args instance:instance];
+        [method invoke];
+    }];
 }
 
 - (NSMutableArray *)insStack
@@ -141,24 +171,33 @@ _Pragma("clang diagnostic pop") \
 
 #pragma mark JS Bridge Management
 
-- (NSInteger)invokeNative:(NSString *)instance tasks:(NSArray *)tasks callback:(NSString __unused*)callback
+- (NSInteger)invokeNative:(NSString *)instanceId tasks:(NSArray *)tasks callback:(NSString __unused*)callback
 {
     WXAssertBridgeThread();
     
-    if (!instance || !tasks) {
+    if (!instanceId || !tasks) {
         WX_MONITOR_FAIL(WXMTNativeRender, WX_ERR_JSFUNC_PARAM, @"JS call Native params error!");
         return 0;
     }
 
-    if (![WXSDKManager instanceForID:instance]) {
-        WXLogInfo(@"instance already destroyed");
+    WXSDKInstance *instance = [WXSDKManager instanceForID:instanceId];
+    if (!instance) {
+        WXLogInfo(@"instance already destroyed, task ignored");
         return -1;
     }
     
     for (NSDictionary *task in tasks) {
-        WXBridgeMethod *method = [[WXBridgeMethod alloc] initWihData:task];
-        method.instance = instance;
-        [[WXInvocationConfig sharedInstance] dispatchMethod:method];
+        NSString *methodName = task[@"method"];
+        NSArray *arguments = task[@"args"];
+        if (task[@"component"]) {
+            NSString *ref = task[@"ref"];
+            WXComponentMethod *method = [[WXComponentMethod alloc] initWithComponentRef:ref methodName:methodName arguments:arguments instance:instance];
+            [method invoke];
+        } else {
+            NSString *moduleName = task[@"module"];
+            WXModuleMethod *method = [[WXModuleMethod alloc] initWithModuleName:moduleName methodName:methodName arguments:arguments instance:instance];
+            [method invoke];
+        }
     }
     
     [self performSelector:@selector(_sendQueueLoop) withObject:nil];
@@ -255,6 +294,8 @@ _Pragma("clang diagnostic pop") \
         //the JSFramework has been load successfully.
         self.frameworkLoadFinished = YES;
         
+        [self executeAllJsService];
+        
         JSValue *frameworkVersion = [self.jsBridge callJSMethod:@"getJSFMVersion" args:nil];
         if (frameworkVersion && [frameworkVersion isString]) {
             [WXAppConfiguration setJSFrameworkVersion:[frameworkVersion toString]];
@@ -271,7 +312,7 @@ _Pragma("clang diagnostic pop") \
     };
 }
 
-- (void)executeJsMethod:(WXBridgeMethod *)method
+- (void)executeJsMethod:(WXCallJSMethod *)method
 {
     WXAssertBridgeThread();
     
@@ -280,9 +321,9 @@ _Pragma("clang diagnostic pop") \
         return;
     }
     
-    NSMutableArray *sendQueue = self.sendQueue[method.instance];
+    NSMutableArray *sendQueue = self.sendQueue[method.instance.instanceId];
     if (!sendQueue) {
-        WXLogInfo(@"No send queue for instance:%@, may it has been destroyed so method:%@ is ignored", method.instance, method.method);
+        WXLogInfo(@"No send queue for instance:%@, may it has been destroyed so method:%@ is ignored", method.instance, method.methodName);
         return;
     }
     
@@ -290,6 +331,37 @@ _Pragma("clang diagnostic pop") \
     [self performSelector:@selector(_sendQueueLoop) withObject:nil];
 }
 
+- (void)executeAllJsService
+{
+    for(NSDictionary *service in _jsServiceQueue) {
+        NSString *script = [service valueForKey:@"script"];
+        NSString *name = [service valueForKey:@"name"];
+        [self executeJsService:script withName:name];
+    }
+    
+    [_jsServiceQueue removeAllObjects];
+}
+
+- (void)executeJsService:(NSString *)script withName:(NSString *)name
+{
+    if(self.frameworkLoadFinished) {
+        WXAssert(script, @"param script required!");
+        [self.jsBridge executeJavascript:script];
+        
+        if ([self.jsBridge exception]) {
+            NSString *message = [NSString stringWithFormat:@"JSService executes error: %@", [self.jsBridge exception]];
+            WX_MONITOR_FAIL(WXMTJSService, WX_ERR_JSFRAMEWORK_EXECUTE, message);
+        } else {
+            // success
+        }
+    }else {
+        [_jsServiceQueue addObject:@{
+                                     @"name": name,
+                                     @"script": script
+                                     }];
+    }
+}
+
 - (void)registerModules:(NSDictionary *)modules
 {
     WXAssertBridgeThread();
@@ -312,8 +384,7 @@ _Pragma("clang diagnostic pop") \
 {
     if (self.frameworkLoadFinished) {
         [self.jsBridge callJSMethod:method args:args];
-    }
-    else {
+    } else {
         [_methodQueue addObject:@{@"method":method, @"args":args}];
     }
 }
@@ -349,40 +420,30 @@ _Pragma("clang diagnostic pop") \
 
 #pragma mark Private Mehtods
 
-- (WXBridgeMethod *)_methodWithCallback:(NSString *)callback
-{
-    WXAssertBridgeThread();
-    
-    if (!callback) return nil;
-    
-    NSDictionary *method = @{@"module":@"jsBridge", @"method":@"callback", @"args":@[callback]};
-    
-    return [[WXBridgeMethod alloc] initWihData:method];
-}
-
 - (void)_sendQueueLoop
 {
     WXAssertBridgeThread();
     
     BOOL hasTask = NO;
-    NSMutableArray *methods = [NSMutableArray array];
+    NSMutableArray *tasks = [NSMutableArray array];
     NSString *execIns = nil;
     
     for (NSString *instance in self.insStack) {
         NSMutableArray *sendQueue = self.sendQueue[instance];
         if(sendQueue.count > 0){
             hasTask = YES;
-            for(WXBridgeMethod *method in sendQueue){
-                [methods addObject:[method dataDesc]];
+            for(WXCallJSMethod *method in sendQueue){
+                [tasks addObject:[method callJSTask]];
             }
+            
             [sendQueue removeAllObjects];
             execIns = instance;
             break;
         }
     }
     
-    if ([methods count] > 0 && execIns) {
-        [self callJSMethod:@"callJS" args:@[execIns, methods]];
+    if ([tasks count] > 0 && execIns) {
+        [self callJSMethod:@"callJS" args:@[execIns, tasks]];
     }
     
     if (hasTask) {

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Bridge/WXCallJSMethod.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXCallJSMethod.h b/ios/sdk/WeexSDK/Sources/Bridge/WXCallJSMethod.h
new file mode 100644
index 0000000..50cdc20
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXCallJSMethod.h
@@ -0,0 +1,20 @@
+/**
+ * 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 "WXBridgeMethod.h"
+
+@interface WXCallJSMethod : WXBridgeMethod
+
+- (instancetype)initWithModuleName:(NSString *)moduleName
+                        methodName:(NSString *)methodName
+                         arguments:(NSArray *)arguments
+                          instance:(WXSDKInstance *)instance;
+
+- (NSDictionary *)callJSTask;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Bridge/WXCallJSMethod.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXCallJSMethod.m b/ios/sdk/WeexSDK/Sources/Bridge/WXCallJSMethod.m
new file mode 100644
index 0000000..ea98885
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXCallJSMethod.m
@@ -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 "WXCallJSMethod.h"
+
+@implementation WXCallJSMethod
+{
+    NSString *_moduleName;
+}
+
+- (instancetype)initWithModuleName:(NSString *)moduleName
+                        methodName:(NSString *)methodName
+                         arguments:(NSArray *)arguments
+                          instance:(WXSDKInstance *)instance
+{
+    if (self = [super initWithMethodName:methodName arguments:arguments instance:instance]) {
+        _moduleName = moduleName;
+    }
+    
+    return self;
+}
+
+- (NSDictionary *)callJSTask
+{
+    return @{@"module":_moduleName ?: @"",
+             @"method":self.methodName ?: @"",
+             @"args":self.arguments ?: @[]};
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Bridge/WXComponentMethod.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXComponentMethod.h b/ios/sdk/WeexSDK/Sources/Bridge/WXComponentMethod.h
new file mode 100644
index 0000000..5906e09
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXComponentMethod.h
@@ -0,0 +1,21 @@
+/**
+ * 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 "WXBridgeMethod.h"
+@class WXComponent;
+
+@interface WXComponentMethod : WXBridgeMethod
+
+- (instancetype)initWithComponentRef:(NSString *)ref
+                          methodName:(NSString *)methodName
+                           arguments:(NSArray *)arguments
+                            instance:(WXSDKInstance *)instance;
+
+- (void)invoke;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Bridge/WXComponentMethod.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXComponentMethod.m b/ios/sdk/WeexSDK/Sources/Bridge/WXComponentMethod.m
new file mode 100644
index 0000000..e8c5225
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXComponentMethod.m
@@ -0,0 +1,51 @@
+/**
+ * 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 "WXComponentMethod.h"
+#import "WXComponentFactory.h"
+#import "WXComponentManager.h"
+#import "WXSDKInstance.h"
+#import "WXLog.h"
+#import "WXUtility.h"
+
+@implementation WXComponentMethod
+{
+    NSString *_componentName;
+    NSString *_componentRef;
+}
+
+- (instancetype)initWithComponentRef:(NSString *)ref
+                          methodName:(NSString *)methodName
+                           arguments:(NSArray *)arguments
+                            instance:(WXSDKInstance *)instance
+{
+    if (self = [super initWithMethodName:methodName arguments:arguments instance:instance]) {
+        _componentRef = ref;
+    }
+    
+    return self;
+}
+
+- (void)invoke
+{
+    WXPerformBlockOnComponentThread(^{
+        WXComponent *component = [self.instance componentForRef:_componentRef];
+        if (!component) {
+            WXLogError(@"component not found for ref:%@, type:%@", _componentRef, _componentName);
+        }
+        SEL selector = [WXComponentFactory methodWithComponentName:component.type withMethod:self.methodName];
+        NSInvocation * invocation = [self invocationWithTarget:component selector:selector];
+        WXPerformBlockOnMainThread(^{
+            [invocation invoke];
+        });
+    });
+    
+    
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Bridge/WXDebugLoggerBridge.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXDebugLoggerBridge.m b/ios/sdk/WeexSDK/Sources/Bridge/WXDebugLoggerBridge.m
index 9a966cd..f9c8702 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXDebugLoggerBridge.m
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXDebugLoggerBridge.m
@@ -108,6 +108,11 @@
 
 #pragma mark - WXBridgeProtocol
 
+- (void)executeJavascript:(NSString *)script
+{
+    [self callJSMethod:@"evalFramework" args:@[script]];
+}
+
 - (void)executeJSFramework:(NSString *)frameworkScript
 {
     [self callJSMethod:@"evalFramework" args:@[frameworkScript]];

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.m b/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.m
index d1c6551..cc43945 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.m
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.m
@@ -20,6 +20,7 @@
 #import <sys/utsname.h>
 #import <JavaScriptCore/JavaScriptCore.h>
 #import "WXPolyfillSet.h"
+#import "JSValue+Weex.h"
 
 #import <dlfcn.h>
 
@@ -139,11 +140,16 @@
     _jsContext[@"callNative"] = callNativeBlock;
 }
 
+- (void)executeJavascript:(NSString *)script
+{
+    WXAssertParam(script);
+    [_jsContext evaluateScript:script];
+}
+
 - (void)registerCallAddElement:(WXJSCallAddElement)callAddElement
 {
     id callAddElementBlock = ^(JSValue *instanceId, JSValue *ref, JSValue *element, JSValue *index, JSValue *ifCallback) {
         
-        // Temporary here , in order to improve performance, will be refactored next version.
         NSString *instanceIdString = [instanceId toString];
         NSDictionary *componentData = [element toDictionary];
         NSString *parentRef = [ref toString];
@@ -157,6 +163,38 @@
     _jsContext[@"callAddElement"] = callAddElementBlock;
 }
 
+- (void)registerCallNativeModule:(WXJSCallNativeModule)callNativeModuleBlock
+{
+    _jsContext[@"callNativeModule"] = ^JSValue *(JSValue *instanceId, JSValue *moduleName, JSValue *methodName, JSValue *args, JSValue *options) {
+        NSString *instanceIdString = [instanceId toString];
+        NSString *moduleNameString = [moduleName toString];
+        NSString *methodNameString = [methodName toString];
+        NSArray *argsArray = [args toArray];
+        NSDictionary *optionsDic = [options toDictionary];
+        
+        WXLogDebug(@"callNativeModule...%@,%@,%@,%@", instanceIdString, moduleNameString, methodNameString, argsArray);
+        
+        NSInvocation *invocation = callNativeModuleBlock(instanceIdString, moduleNameString, methodNameString, argsArray, optionsDic);
+        JSValue *returnValue = [JSValue wx_valueWithReturnValueFromInvocation:invocation inContext:[JSContext currentContext]];
+        return returnValue;
+    };
+}
+
+- (void)registerCallNativeComponent:(WXJSCallNativeComponent)callNativeComponentBlock
+{
+    _jsContext[@"callNativeComponent"] = ^void(JSValue *instanceId, JSValue *componentName, JSValue *methodName, JSValue *args, JSValue *options) {
+        NSString *instanceIdString = [instanceId toString];
+        NSString *componentNameString = [componentName toString];
+        NSString *methodNameString = [methodName toString];
+        NSArray *argsArray = [args toArray];
+        NSDictionary *optionsDic = [options toDictionary];
+        
+        WXLogDebug(@"callNativeModule...%@,%@,%@,%@", instanceIdString, componentNameString, methodNameString, argsArray);
+        
+        callNativeComponentBlock(instanceIdString, componentNameString, methodNameString, argsArray, optionsDic);
+    };
+}
+
 - (JSValue*)exception
 {
     return _jsContext.exception;

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Bridge/WXModuleMethod.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXModuleMethod.h b/ios/sdk/WeexSDK/Sources/Bridge/WXModuleMethod.h
new file mode 100644
index 0000000..1a4107d
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXModuleMethod.h
@@ -0,0 +1,28 @@
+/**
+ * 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 "WXBridgeMethod.h"
+
+typedef enum : NSUInteger {
+    WXModuleMethodTypeSync,
+    WXModuleMethodTypeAsync,
+} WXModuleMethodType;
+
+@interface WXModuleMethod : WXBridgeMethod
+
+@property (nonatomic, assign) WXModuleMethodType methodType;
+@property (nonatomic, strong, readonly) NSString *moduleName;
+
+- (instancetype)initWithModuleName:(NSString *)moduleName
+                        methodName:(NSString *)methodName
+                         arguments:(NSArray *)arguments
+                          instance:(WXSDKInstance *)instance;
+
+- (NSInvocation *)invoke;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Bridge/WXModuleMethod.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXModuleMethod.m b/ios/sdk/WeexSDK/Sources/Bridge/WXModuleMethod.m
new file mode 100644
index 0000000..de07eca
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXModuleMethod.m
@@ -0,0 +1,99 @@
+/**
+ * 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 "WXModuleMethod.h"
+#import "WXModuleFactory.h"
+#import "WXMonitor.h"
+#import "WXModuleProtocol.h"
+#import "WXAssert.h"
+#import "WXUtility.h"
+#import "WXSDKInstance_private.h"
+
+@implementation WXModuleMethod
+
+- (instancetype)initWithModuleName:(NSString *)moduleName
+                        methodName:(NSString *)methodName
+                         arguments:(NSArray *)arguments
+                          instance:(WXSDKInstance *)instance
+{
+    if (self = [super initWithMethodName:methodName arguments:arguments instance:instance]) {
+        _moduleName = moduleName;
+    }
+    
+    return self;
+}
+
+- (NSInvocation *)invoke
+{
+    Class moduleClass =  [WXModuleFactory classWithModuleName:_moduleName];
+    if (!moduleClass) {
+        NSString *errorMessage = [NSString stringWithFormat:@"Module\uff1a%@ doesn't exist, maybe it has not been registered", _moduleName];
+        WX_MONITOR_FAIL(WXMTJSBridge, WX_ERR_INVOKE_NATIVE, errorMessage);
+        return nil;
+    }
+    
+    id<WXModuleProtocol> moduleInstance = [self.instance moduleForClass:moduleClass];
+    WXAssert(moduleInstance, @"No instance found for module name:%@, class:%@", _moduleName, moduleClass);
+    BOOL isSync = NO;
+    SEL selector = [WXModuleFactory selectorWithModuleName:self.moduleName methodName:self.methodName isSync:&isSync];
+    if (!selector) {
+        NSString *errorMessage = [NSString stringWithFormat:@"method\uff1a%@ for module:%@ doesn't exist, maybe it has not been registered", self.methodName, _moduleName];
+        WX_MONITOR_FAIL(WXMTJSBridge, WX_ERR_INVOKE_NATIVE, errorMessage);
+        return nil;;
+    }
+    if (![moduleInstance respondsToSelector:selector]) {
+        // if not implement the selector, then dispatch default module method
+        if ([self.methodName isEqualToString:@"addEventListener"]) {
+            [self.instance _addModuleEventObserversWithModuleMethod:self];
+        }
+        if ([self.methodName isEqualToString:@"removeAllEventListeners"]) {
+            [self.instance _removeModuleEventObserverWithModuleMethod:self];
+        }
+        return nil;
+    }
+    
+    NSInvocation *invocation = [self invocationWithTarget:moduleInstance selector:selector];
+    
+    if (isSync) {
+        [invocation invoke];
+        return invocation;
+    } else {
+        [self _dispatchInvovation:invocation moduleInstance:moduleInstance];
+        return nil;
+    }
+}
+
+- (void)_dispatchInvovation:(NSInvocation *)invocation moduleInstance:(id<WXModuleProtocol>)moduleInstance
+{
+    // dispatch to user specified queue or thread, default is main thread
+    dispatch_block_t dipatchBlock = ^ (){
+        [invocation invoke];
+    };
+    
+    NSThread *targetThread = nil;
+    dispatch_queue_t targetQueue = nil;
+    if([moduleInstance respondsToSelector:@selector(targetExecuteQueue)]){
+        targetQueue = [moduleInstance targetExecuteQueue] ?: dispatch_get_main_queue();
+    } else if([moduleInstance respondsToSelector:@selector(targetExecuteThread)]){
+        targetThread = [moduleInstance targetExecuteThread] ?: [NSThread mainThread];
+    } else {
+        targetThread = [NSThread mainThread];
+    }
+    
+    WXAssert(targetQueue || targetThread, @"No queue or thread found for module:%@", moduleInstance);
+    
+    if (targetQueue) {
+        dispatch_async(targetQueue, dipatchBlock);
+    } else {
+        WXPerformBlockOnThread(^{
+            dipatchBlock();
+        }, targetThread);
+    }
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Component/WXCanvasComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXCanvasComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXCanvasComponent.m
index f83f1c9..8dbba33 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXCanvasComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/WXCanvasComponent.m
@@ -165,7 +165,7 @@
 
 
 // OpenGL ES methods map
-#define WX_CANVAS_PIXEL(name, index) WXPixelType name = [WXConvert WXPixelType:params[index]];
+#define WX_CANVAS_PIXEL(name, index) WXPixelType name = [WXConvert WXPixelType:params[index] scaleFactor:self.weexInstance.pixelScaleFactor];
 #define WX_CANVAS_CGFLOAT(name, index) CGFloat name = [WXConvert CGFloat:params[index]];
 #define WX_CANVAS_PARAMS_CHECK(num) if ([params count] < num) return;
 
@@ -196,10 +196,10 @@
         CGFloat sy = [WXConvert CGFloat:curParams[1]];
         CGFloat sw = [WXConvert CGFloat:curParams[2]];
         CGFloat sh = [WXConvert CGFloat:curParams[3]];
-        CGFloat dx = [WXConvert WXPixelType:curParams[4]];
-        CGFloat dy = [WXConvert WXPixelType:curParams[5]];
-        CGFloat dw = [WXConvert WXPixelType:curParams[6]];
-        CGFloat dh = [WXConvert WXPixelType:curParams[7]];
+        CGFloat dx = [WXConvert WXPixelType:curParams[4] scaleFactor:self.weexInstance.pixelScaleFactor];
+        CGFloat dy = [WXConvert WXPixelType:curParams[5] scaleFactor:self.weexInstance.pixelScaleFactor];
+        CGFloat dw = [WXConvert WXPixelType:curParams[6] scaleFactor:self.weexInstance.pixelScaleFactor];
+        CGFloat dh = [WXConvert WXPixelType:curParams[7] scaleFactor:self.weexInstance.pixelScaleFactor];
 
         geometrys[i * 4] = GLKVector3Make(dx, dh + dy, 1);
         geometrys[i * 4 + 1] = GLKVector3Make(dw + dx, dh + dy, 1);
@@ -221,7 +221,7 @@
                                                [WXConvert CGFloat:curParams[16]]
             );
             // Because the params are base on 750, so we should make scale for the transform matrix
-            matrix = GLKMatrix3Scale(matrix, 1, 1, WXScreenResizeRadio());
+            matrix = GLKMatrix3Scale(matrix, 1, 1, self.weexInstance.pixelScaleFactor);
             geometrys[i * 4] = GLKMatrix3MultiplyVector3(matrix, geometrys[i * 4]);
             geometrys[i * 4 + 1] = GLKMatrix3MultiplyVector3(matrix, geometrys[i * 4 + 1]);
             geometrys[i * 4 + 2] = GLKMatrix3MultiplyVector3(matrix, geometrys[i * 4 + 2]);
@@ -311,7 +311,7 @@
 - (void) setLineWidth:(NSArray *)params
 {
     WX_CANVAS_PARAMS_CHECK(1);
-    _curLineWidth = [WXConvert WXPixelType:params[0]];
+    _curLineWidth = [WXConvert WXPixelType:params[0] scaleFactor:self.weexInstance.pixelScaleFactor];
 }
 
 // ["M", 0, 0, "L", 100, 100, "L", 0, 100, "L", 0, 0] it made a triangle
@@ -327,7 +327,7 @@
 
     for (GLint i = 0; i < params.count; i += 3) {
         NSString *type = [WXConvert NSString:params[i]];
-        points[pointIndex] = GLKVector2Make([WXConvert WXPixelType:params[i + 1]], [WXConvert WXPixelType:params[i + 2]]);
+        points[pointIndex] = GLKVector2Make([WXConvert WXPixelType:params[i + 1] scaleFactor:self.weexInstance.pixelScaleFactor], [WXConvert WXPixelType:params[i + 2] scaleFactor:self.weexInstance.pixelScaleFactor]);
 
         if ([type isEqualToString:@"L"]) {
             if (isLastMove) {

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.h b/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.h
index a0656dd..544fbfe 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.h
+++ b/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.h
@@ -12,6 +12,8 @@
 @interface WXCellComponent : WXComponent
 
 @property (nonatomic, strong) NSString *scope;
+@property (nonatomic, assign) UITableViewRowAnimation insertAnimation;
+@property (nonatomic, assign) UITableViewRowAnimation deleteAnimation;
 @property (nonatomic, weak) WXListComponent *list;
 
-@end
\ No newline at end of file
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m
index 5a11065..0483ec0 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m
@@ -23,6 +23,8 @@
     
     if (self) {
         _async = attributes[@"async"] ? [WXConvert BOOL:attributes[@"async"]] : YES;
+        _insertAnimation = [WXConvert UITableViewRowAnimation:attributes[@"insertAnimation"]];
+        _deleteAnimation = [WXConvert UITableViewRowAnimation:attributes[@"deleteAnimation"]];
         _lazyCreateView = YES;
         _isNeedJoinLayoutSystem = NO;
     }
@@ -60,6 +62,14 @@
     if (attributes[@"async"]) {
         _async = [WXConvert BOOL:attributes[@"async"]];
     }
+    
+    if (attributes[@"insertAnimation"]) {
+        _insertAnimation = [WXConvert UITableViewRowAnimation:attributes[@"insertAnimation"]];
+    }
+    
+    if (attributes[@"deleteAnimation"]) {
+        _deleteAnimation = [WXConvert UITableViewRowAnimation:attributes[@"deleteAnimation"]];
+    }
 }
 
 - (void)_moveToSupercomponent:(WXComponent *)newSupercomponent atIndex:(NSUInteger)index

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Component/WXComponent+GradientColor.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXComponent+GradientColor.h b/ios/sdk/WeexSDK/Sources/Component/WXComponent+GradientColor.h
new file mode 100644
index 0000000..0706eed
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/WXComponent+GradientColor.h
@@ -0,0 +1,20 @@
+//
+//  WXComponent+GradientColor.h
+//  Pods
+//
+//  Created by bobning on 16/12/23.
+//
+//
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+#import "WXComponent.h"
+#import "WXType.h"
+
+@interface WXComponent (GradientColor)
+
+- (void)setGradientLayer;
+
+- (UIImage *)gradientColorImageFromColors:(NSArray*)colors gradientType:(WXGradientType)gradientType imgSize:(CGSize)imgSize;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Component/WXComponent+GradientColor.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXComponent+GradientColor.m b/ios/sdk/WeexSDK/Sources/Component/WXComponent+GradientColor.m
new file mode 100644
index 0000000..e710ed0
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/WXComponent+GradientColor.m
@@ -0,0 +1,116 @@
+//
+//  WXComponent+GradientColor.m
+//  Pods
+//
+//  Created by bobning on 16/12/23.
+//
+//
+
+#import "WXComponent+GradientColor.h"
+#import "WXComponent_internal.h"
+#import "WXConvert.h"
+
+@implementation  WXComponent (GradientColor)
+
+- (void)setGradientLayer {
+    //parse gradient-color, linear-gradient(to right, #a80077,rgba(200, 54, 54, 0.5))
+    if ([_backgroundImage hasPrefix:@"linear-gradient"] && [_backgroundImage hasSuffix:@")"] ) {
+        NSRange range = NSMakeRange(16, _backgroundImage.length - 17);
+        NSString *str = [_backgroundImage substringWithRange:range];
+        NSArray *array = [str componentsSeparatedByString:@","];
+        WXGradientType gradientType;
+        UIColor *startColor, *endColor;
+        
+        if ([array count] == 3) {
+            gradientType = [WXConvert gradientType:array[0]];
+            startColor = [WXConvert UIColor:array[1]];
+            endColor = [WXConvert UIColor:array[2]];
+        }
+        else if ([array count] > 3){
+            NSString *gradientTypeStr = array[0];
+            NSString *subStr = [str substringFromIndex:gradientTypeStr.length + 1];
+            
+            if ([subStr hasPrefix:@"rgb"]) {
+                gradientType = [WXConvert gradientType:gradientTypeStr];
+                
+                range = [subStr rangeOfString:@")"];
+                NSString *startColorStr = [subStr substringToIndex:range.location + 1];
+                NSString *endColorStr = [subStr substringFromIndex:range.location + 2];
+                startColor = [WXConvert UIColor:startColorStr];
+                endColor = [WXConvert UIColor:endColorStr];
+            }
+            else {
+                gradientType = [WXConvert gradientType:gradientTypeStr];
+                
+                startColor = [WXConvert UIColor:array[1]];
+                
+                NSString *startColorStr = array[1];
+                NSString *endColorStr = [subStr substringFromIndex:startColorStr.length + 1];
+                endColor = [WXConvert UIColor:endColorStr];
+            }
+        }
+        else {
+            return;
+        }
+    
+        __weak typeof(self) weakSelf = self;
+        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+            UIImage *bgImg = [weakSelf gradientColorImageFromColors:@[startColor, endColor] gradientType:gradientType imgSize:weakSelf.view.frame.size];
+            dispatch_async(dispatch_get_main_queue(), ^{
+                weakSelf.view.backgroundColor = [UIColor colorWithPatternImage:bgImg];
+            });
+        });
+    }
+}
+
+- (UIImage *)gradientColorImageFromColors:(NSArray*)colors gradientType:(WXGradientType)gradientType imgSize:(CGSize)imgSize;{
+    NSMutableArray *array = [NSMutableArray array];
+    for(UIColor *color in colors) {
+        [array addObject:(id)color.CGColor];
+    }
+    
+    UIGraphicsBeginImageContextWithOptions(imgSize, YES, 1);
+    CGContextRef context = UIGraphicsGetCurrentContext();
+    CGContextSaveGState(context);
+    CGColorSpaceRef colorSpace = CGColorGetColorSpace([[colors lastObject] CGColor]);
+    CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (CFArrayRef)array, NULL);
+    CGPoint start;
+    CGPoint end;
+    switch (gradientType) {
+        case WXGradientTypeToTop:
+            start = CGPointMake(0.0, imgSize.height);
+            end = CGPointMake(0.0, 0.0);
+            break;
+        case WXGradientTypeToBottom:
+            start = CGPointMake(0.0, 0.0);
+            end = CGPointMake(0.0, imgSize.height);
+            break;
+        case WXGradientTypeToLeft:
+            start = CGPointMake(imgSize.width, 0.0);
+            end = CGPointMake(0.0, 0.0);
+            break;
+        case WXGradientTypeToRight:
+            start = CGPointMake(0.0, 0.0);
+            end = CGPointMake(imgSize.width, 0.0);
+            break;
+        case WXGradientTypeToTopleft:
+            start = CGPointMake(imgSize.width, imgSize.height);
+            end = CGPointMake(0.0, 0.0f);
+            break;
+        case WXGradientTypeToBottomright:
+            start = CGPointMake(0.0, 0.0);
+            end = CGPointMake(imgSize.width, imgSize.height);
+            break;
+        default:
+            break;
+    }
+    CGContextDrawLinearGradient(context, gradient, start, end, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
+    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
+    CGGradientRelease(gradient);
+    CGContextRestoreGState(context);
+    CGColorSpaceRelease(colorSpace);
+    UIGraphicsEndImageContext();
+    return image;
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
index d09ce42..04f5440 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
+++ b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
@@ -34,12 +34,20 @@
      *  View
      */
     UIColor *_backgroundColor;
+    NSString *_backgroundImage;
     WXClipType _clipToBounds;
     UIView *_view;
     CGFloat _opacity;
     WXVisibility  _visibility;
     
     /**
+     *  PseudoClass
+     */
+    NSMutableDictionary *_pseudoClassStyles;
+    NSMutableDictionary *_updatedPseudoClassStyles;
+    BOOL _isListenPseudoTouch;
+    
+    /**
      *  Events
      */
     BOOL _appearEvent;
@@ -48,9 +56,14 @@
     NSMutableArray *_swipeGestures;
     UILongPressGestureRecognizer *_longPressGesture;
     UIPanGestureRecognizer *_panGesture;
+    
     BOOL _listenPanStart;
     BOOL _listenPanMove;
     BOOL _listenPanEnd;
+    
+    BOOL _listenHorizontalPan;
+    BOOL _listenVerticalPan;
+    
     WXTouchGestureRecognizer* _touchGesture;
     
     /**
@@ -110,7 +123,7 @@
 - (void)_removeFromSupercomponent;
 - (void)_moveToSupercomponent:(WXComponent *)newSupercomponent atIndex:(NSUInteger)index;
 
-- (void)_updateStylesOnComponentThread:(NSDictionary *)styles resetStyles:(NSMutableArray *)resetStyles;
+- (void)_updateStylesOnComponentThread:(NSDictionary *)styles resetStyles:(NSMutableArray *)resetStyles isUpdateStyles:(BOOL)isUpdateStyles;
 - (void)_updateAttributesOnComponentThread:(NSDictionary *)attributes;
 - (void)_updateStylesOnMainThread:(NSDictionary *)styles resetStyles:(NSMutableArray *)resetStyles;
 - (void)_updateAttributesOnMainThread:(NSDictionary *)attributes;
@@ -156,6 +169,8 @@
 
 - (void)_initEvents:(NSArray *)events;
 
+- (void)_initPseudoEvents:(BOOL)isListenPseudoTouch;
+
 - (void)_removeAllEvents;
 
 - (void)_setupNavBarWithStyles:(NSMutableDictionary *)styles attributes:(NSMutableDictionary *)attributes;
@@ -166,4 +181,7 @@
 
 - (void)_resetNativeBorderRadius;
 
+- (void)_updatePseudoClassStyles:(NSString *)key;
+
+- (void)_restoreViewStyles;
 @end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Component/WXEmbedComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXEmbedComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXEmbedComponent.m
index 1d47b4d..3b1df98 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXEmbedComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/WXEmbedComponent.m
@@ -151,16 +151,18 @@
     };
     
     _embedInstance.onFailed = ^(NSError *error) {
-        if (weakSelf.errorView) {
-            return ;
-        }
-        
-        WXErrorView *errorView = [[WXErrorView alloc]initWithFrame:CGRectMake(0.0f, 0.0f, 135.0f, 130.0f)];
-        errorView.center = CGPointMake(weakSelf.view.bounds.size.width / 2.0f, weakSelf.view.bounds.size.height / 2.0f);
-        errorView.delegate = weakSelf;
-        [weakSelf.view addSubview:errorView];
-        
-        weakSelf.errorView = errorView;
+        dispatch_async(dispatch_get_main_queue(), ^{
+            if (weakSelf.errorView) {
+                return ;
+            }
+            
+            WXErrorView *errorView = [[WXErrorView alloc]initWithFrame:CGRectMake(0.0f, 0.0f, 135.0f, 130.0f)];
+            errorView.center = CGPointMake(weakSelf.view.bounds.size.width / 2.0f, weakSelf.view.bounds.size.height / 2.0f);
+            errorView.delegate = weakSelf;
+            [weakSelf.view addSubview:errorView];
+            
+            weakSelf.errorView = errorView;
+        });
     };
     
     _embedInstance.renderFinish = ^(UIView *view) {

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m
index 6baac1d..20b80aa 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m
@@ -34,6 +34,7 @@ static dispatch_queue_t WXImageUpdateQueue;
 
 @property (nonatomic, strong) NSString *imageSrc;
 @property (nonatomic, strong) NSString *placeholdSrc;
+@property (nonatomic, assign) CGFloat blurRadius;
 @property (nonatomic, assign) UIViewContentMode resizeMode;
 @property (nonatomic, assign) WXImageQuality imageQuality;
 @property (nonatomic, assign) WXImageSharp imageSharp;
@@ -41,6 +42,7 @@ static dispatch_queue_t WXImageUpdateQueue;
 @property (nonatomic, strong) id<WXImageOperationProtocol> imageOperation;
 @property (nonatomic, strong) id<WXImageOperationProtocol> placeholderOperation;
 @property (nonatomic) BOOL imageLoadEvent;
+@property (nonatomic) BOOL imageDownloadFinish;
 
 @end
 
@@ -60,9 +62,11 @@ static dispatch_queue_t WXImageUpdateQueue;
         }
         [self configPlaceHolder:attributes];
         _resizeMode = [WXConvert UIViewContentMode:attributes[@"resize"]];
+        [self configFilter:styles];
         _imageQuality = [WXConvert WXImageQuality:styles[@"quality"]];
         _imageSharp = [WXConvert WXImageSharp:styles[@"sharpen"]];
         _imageLoadEvent = NO;
+        _imageDownloadFinish = NO;
     }
     
     return self;
@@ -74,6 +78,27 @@ static dispatch_queue_t WXImageUpdateQueue;
     }
 }
 
+- (void)configFilter:(NSDictionary *)styles {
+    if (styles[@"filter"]) {
+        NSString *filter = styles[@"filter"];
+        
+        NSString *pattern = @"blur\\((\\d+)(px)?\\)";
+        NSError *error = nil;
+        NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern
+                                                                               options:NSRegularExpressionCaseInsensitive
+                                                                                 error:&error];
+        NSArray *matches = [regex matchesInString:filter options:0 range:NSMakeRange(0, filter.length)];
+        if (matches && matches.count > 0) {
+            NSTextCheckingResult *match = matches[matches.count - 1];
+            NSRange matchRange = [match rangeAtIndex:1];
+            NSString *matchString = [filter substringWithRange:matchRange];
+            if (matchString && matchString.length > 0) {
+                _blurRadius = [matchString doubleValue];
+            }
+        }
+    }
+}
+
 - (UIView *)loadView
 {
     return [[WXImageView alloc] init];
@@ -102,6 +127,7 @@ static dispatch_queue_t WXImageUpdateQueue;
         _imageSharp = [WXConvert WXImageSharp:styles[@"sharpen"]];
         [self updateImage];
     }
+    [self configFilter:styles];
 }
 
 - (void)updateAttributes:(NSDictionary *)attributes
@@ -176,6 +202,7 @@ static dispatch_queue_t WXImageUpdateQueue;
 {
     if (![src isEqualToString:_imageSrc]) {
         _imageSrc = src;
+        _imageDownloadFinish = NO;
         [self updateImage];
     }
 }
@@ -187,6 +214,7 @@ static dispatch_queue_t WXImageUpdateQueue;
         [self cancelImage];
         
         void(^downloadFailed)(NSString *, NSError *) = ^void(NSString *url, NSError *error){
+            weakSelf.imageDownloadFinish = YES;
             WXLogError(@"Error downloading image:%@, detail:%@", url, [error localizedDescription]);
         };
         
@@ -196,6 +224,8 @@ static dispatch_queue_t WXImageUpdateQueue;
         if (!weakSelf.imageSrc && !weakSelf.placeholdSrc) {
             dispatch_async(dispatch_get_main_queue(), ^{
                 self.layer.contents = nil;
+                weakSelf.imageDownloadFinish = YES;
+                [weakSelf readyToRender];
             });
         }
     });
@@ -208,7 +238,7 @@ static dispatch_queue_t WXImageUpdateQueue;
     if (placeholderSrc) {
         WXLogDebug(@"Updating image, component:%@, placeholder:%@ ", self.ref, placeholderSrc);
         NSMutableString *newURL = [_placeholdSrc mutableCopy];
-        WX_REWRITE_URL(_placeholdSrc, WXResourceTypeLink, self.weexInstance, &newURL)
+        WX_REWRITE_URL(_placeholdSrc, WXResourceTypeImage, self.weexInstance, &newURL)
         
         __weak typeof(self) weakSelf = self;
         self.placeholderOperation = [[self imageLoader] downloadImageWithURL:newURL imageFrame:self.calculatedFrame userInfo:nil completed:^(UIImage *image, NSError *error, BOOL finished) {
@@ -219,6 +249,7 @@ static dispatch_queue_t WXImageUpdateQueue;
                     downloadFailedBlock(placeholderSrc,error);
                     if ([strongSelf isViewLoaded] && !viewImage) {
                         ((UIImageView *)(strongSelf.view)).image = nil;
+                        [self readyToRender];
                     }
                     return;
                 }
@@ -228,6 +259,8 @@ static dispatch_queue_t WXImageUpdateQueue;
                 
                 if ([strongSelf isViewLoaded] && !viewImage) {
                     ((UIImageView *)strongSelf.view).image = image;
+                    weakSelf.imageDownloadFinish = YES;
+                    [self readyToRender];
                 }
             });
         }];
@@ -236,13 +269,12 @@ static dispatch_queue_t WXImageUpdateQueue;
 
 - (void)updateContentImageWithFailedBlock:(void(^)(NSString *, NSError *))downloadFailedBlock
 {
-    
     NSString *imageSrc = self.imageSrc;
     if (imageSrc) {
         WXLogDebug(@"Updating image:%@, component:%@", self.imageSrc, self.ref);
-        NSDictionary *userInfo = @{@"imageQuality":@(self.imageQuality), @"imageSharp":@(self.imageSharp)};
+        NSDictionary *userInfo = @{@"imageQuality":@(self.imageQuality), @"imageSharp":@(self.imageSharp), @"blurRadius":@(self.blurRadius)};
         NSMutableString * newURL = [imageSrc mutableCopy];
-        WX_REWRITE_URL(imageSrc, WXResourceTypeLink, self.weexInstance, &newURL)
+        WX_REWRITE_URL(imageSrc, WXResourceTypeImage, self.weexInstance, &newURL)
         __weak typeof(self) weakSelf = self;
         dispatch_async(dispatch_get_main_queue(), ^{
             weakSelf.imageOperation = [[weakSelf imageLoader] downloadImageWithURL:newURL imageFrame:weakSelf.calculatedFrame userInfo:userInfo completed:^(UIImage *image, NSError *error, BOOL finished) {
@@ -250,10 +282,14 @@ static dispatch_queue_t WXImageUpdateQueue;
                     __strong typeof(self) strongSelf = weakSelf;
                     
                     if (weakSelf.imageLoadEvent) {
-                        [strongSelf fireEvent:@"load" params:@{ @"success": error? @"false" : @"true"}];
+                        NSMutableDictionary *sizeDict = [NSMutableDictionary new];
+                        sizeDict[@"naturalWidth"] = @(image.size.width * image.scale);
+                        sizeDict[@"naturalHeight"] = @(image.size.height * image.scale);
+                        [strongSelf fireEvent:@"load" params:@{ @"success": error? @false : @true,@"size":sizeDict}];
                     }
                     if (error) {
                         downloadFailedBlock(imageSrc, error);
+                        [strongSelf readyToRender];
                         return ;
                     }
                     
@@ -262,7 +298,9 @@ static dispatch_queue_t WXImageUpdateQueue;
                     }
                     
                     if ([strongSelf isViewLoaded]) {
+                        strongSelf.imageDownloadFinish = YES;
                         ((UIImageView *)strongSelf.view).image = image;
+                        [strongSelf readyToRender];
                     }
                 });
             }];
@@ -270,6 +308,14 @@ static dispatch_queue_t WXImageUpdateQueue;
     }
 }
 
+- (void)readyToRender
+{
+    // when image download completely (success or failed)
+    if (self.weexInstance.trackComponent && _imageDownloadFinish) {
+        [super readyToRender];
+    }
+}
+
 - (void)cancelImage
 {
     [_imageOperation cancel];

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Component/WXIndicatorComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXIndicatorComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXIndicatorComponent.m
index 00fc7e1..5b2b858 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXIndicatorComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/WXIndicatorComponent.m
@@ -10,6 +10,7 @@
 #import "WXSliderComponent.h"
 #import "WXConvert.h"
 #import "WXSliderNeighborComponent.h"
+#import "WXSDKInstance.h"
 
 @implementation WXIndicatorView
 
@@ -136,7 +137,7 @@
     if (self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]) {
         _itemColor = styles[@"itemColor"] ? [WXConvert UIColor:styles[@"itemColor"]]:[UIColor colorWithRed:0xff/255.0f green:0xff/255.0f blue:0xff/255.0f alpha:0.5f];
         _itemSelectedColor = styles[@"itemSelectedColor"] ? [WXConvert UIColor:styles[@"itemSelectedColor"]]:[UIColor colorWithRed:0xff/255.0f green:0xd5/255.0f blue:0x45/255.0f alpha:1.0f];
-        _itemSize = styles[@"itemSize"] ? [WXConvert WXPixelType:styles[@"itemSize"]] : 5.0f;
+        _itemSize = styles[@"itemSize"] ? [WXConvert WXPixelType:styles[@"itemSize"] scaleFactor:self.weexInstance.pixelScaleFactor] : 5.0f;
     }
     return self;
 }
@@ -185,7 +186,7 @@
     
     if (styles[@"itemSize"]) {
         styleChange = YES;
-        _itemSize = [WXConvert WXPixelType:styles[@"itemSize"]];
+        _itemSize = [WXConvert WXPixelType:styles[@"itemSize"] scaleFactor:self.weexInstance.pixelScaleFactor];
         [_indicatorView setPointSize:_itemSize];
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Component/WXListComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXListComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXListComponent.m
index 8e6a611..bea72d0 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXListComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/WXListComponent.m
@@ -36,6 +36,20 @@
     [self.wx_component layoutDidFinish];
 }
 
+- (void)setContentOffset:(CGPoint)contentOffset
+{
+    // FIXME: side effect caused by hooking _adjustContentOffsetIfNecessary.
+    // When UITableView is pulled down and finger releases\uff0ccontentOffset will be set from -xxxx to about -0.5(greater than -0.5), then contentOffset will be reset to zero by calling _adjustContentOffsetIfNecessary.
+    // So hooking _adjustContentOffsetIfNecessary will always cause remaining 1px space between list's top and navigator.
+    // Demo: http://dotwe.org/895630945793a9a044e49abe39cbb77f
+    // Have to reset contentOffset to zero manually here.
+    if (fabs(contentOffset.y) < 0.5) {
+        contentOffset.y = 0;
+    }
+    
+    [super setContentOffset:contentOffset];
+}
+
 @end
 
 @interface WXHeaderComponent : WXComponent
@@ -209,7 +223,7 @@
     NSIndexPath *toIndexPath = [self indexPathForCell:(WXCellComponent*)cellComponent sections:_completedSections];
     CGRect cellRect = [_tableView rectForRowAtIndexPath:toIndexPath];
     contentOffsetY += cellRect.origin.y;
-    contentOffsetY += offset * WXScreenResizeRadio();
+    contentOffsetY += offset * self.weexInstance.pixelScaleFactor;
     
     if (contentOffsetY > _tableView.contentSize.height - _tableView.frame.size.height) {
         contentOffset.y = _tableView.contentSize.height - _tableView.frame.size.height;
@@ -297,9 +311,15 @@
         [self removeCellForIndexPath:indexPath withSections:_completedSections];
         
         WXLogDebug(@"Delete cell:%@ at indexPath:%@", cell.ref, indexPath);
-        [UIView performWithoutAnimation:^{
-            [_tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
-        }];
+        if (cell.deleteAnimation == UITableViewRowAnimationNone) {
+            [UIView performWithoutAnimation:^{
+                [_tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
+                [self handleAppear];
+            }];
+        } else {
+            [_tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:cell.deleteAnimation];
+            [self handleAppear];
+        }
     }];
 }
 
@@ -327,13 +347,20 @@
         if (!isReload) {
             WXLogDebug(@"Insert cell:%@ at indexPath:%@", cell.ref, indexPath);
             _completedSections = completedSections;
-            [UIView performWithoutAnimation:^{
-                [_tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
-            }];
+            if (cell.insertAnimation == UITableViewRowAnimationNone) {
+                [UIView performWithoutAnimation:^{
+                    [_tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
+                    [self handleAppear];
+                }];
+            } else {
+                [_tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:cell.insertAnimation];
+                [self handleAppear];
+            }
         } else {
             WXLogInfo(@"Reload cell:%@ at indexPath:%@", cell.ref, indexPath);
             [UIView performWithoutAnimation:^{
                 [_tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
+                [self handleAppear];
             }];
         }
     }];
@@ -381,6 +408,7 @@
         [self insertCell:cell forIndexPath:toIndexPath withSections:_completedSections];
         [UIView performWithoutAnimation:^{
             [_tableView moveRowAtIndexPath:fromIndexPath toIndexPath:toIndexPath];
+            [self handleAppear];
         }];
     }];
 }
@@ -603,7 +631,11 @@
 {
     static dispatch_once_t onceToken;
     dispatch_once(&onceToken, ^{
-        //(\u0e07 \u2022\u0300_\u2022\u0301)\u0e07\u253b\u2501\u253b Stupid scoll view, always reset content offset to zero after insert cells, any other more elegant way?
+        // FIXME:(\u0e07 \u2022\u0300_\u2022\u0301)\u0e07\u253b\u2501\u253b Stupid scoll view, always reset content offset to zero by calling _adjustContentOffsetIfNecessary after insert cells.
+        // So if you pull down list while list is rendering, the list will be flickering.
+        // Demo:    
+        // Have to hook _adjustContentOffsetIfNecessary here.
+        // Any other more elegant way?
         NSString *a = @"ntOffsetIfNe";
         NSString *b = @"adjustConte";
         

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.h b/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.h
index d256567..248d03a 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.h
+++ b/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.h
@@ -21,5 +21,7 @@
 
 - (NSUInteger)childrenCountForScrollerLayout;
 
+- (void)handleAppear;
+
 @end
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.m
index 7a72883..fa91d3e 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.m
@@ -44,6 +44,7 @@
     CGFloat _loadMoreOffset;
     CGFloat _previousLoadMoreContentHeight;
     CGPoint _lastContentOffset;
+    BOOL _scrollable;
     
     // vertical & horizontal
     WXScrollDirection _scrollDirection;
@@ -91,6 +92,7 @@ WX_EXPORT_METHOD(@selector(resetLoadmore))
         _loadMoreOffset = attributes[@"loadmoreoffset"] ? [WXConvert CGFloat:attributes[@"loadmoreoffset"]] : 0;
         _loadmoreretry = attributes[@"loadmoreretry"] ? [WXConvert NSUInteger:attributes[@"loadmoreretry"]] : 0;
         _listenLoadMore = [events containsObject:@"loadmore"];
+        _scrollable = attributes[@"scrollable"] ? [WXConvert BOOL:attributes[@"scrollable"]] : YES;
 
         _scrollerCSSNode = new_css_node();
         
@@ -123,6 +125,7 @@ WX_EXPORT_METHOD(@selector(resetLoadmore))
     scrollView.clipsToBounds = YES;
     scrollView.showsVerticalScrollIndicator = _showScrollBar;
     scrollView.showsHorizontalScrollIndicator = _showScrollBar;
+    scrollView.scrollEnabled = _scrollable;
     
     if (self.ancestorScroller) {
         scrollView.scrollsToTop = NO;
@@ -174,6 +177,10 @@ WX_EXPORT_METHOD(@selector(resetLoadmore))
         }
         self.loadmoreretry = loadmoreretry;
     }
+    if (attributes[@"scrollable"]) {
+        _scrollable = attributes[@"scrollable"] ? [WXConvert BOOL:attributes[@"scrollable"]] : YES;
+        ((UIScrollView *)self.view).scrollEnabled = _scrollable;
+    }
 }
 
 - (void)addEvent:(NSString *)eventName
@@ -215,7 +222,7 @@ WX_EXPORT_METHOD(@selector(resetLoadmore))
     }
     CGFloat scrollOffsetY = ((UIScrollView *)self.view).contentOffset.y;
     for(WXComponent *component in self.stickyArray) {
-        if (CGPointEqualToPoint(component->_absolutePosition, CGPointZero)) {
+        if (isnan(component->_absolutePosition.x) && isnan(component->_absolutePosition.y)) {
             component->_absolutePosition = [component.supercomponent.view convertPoint:component.view.frame.origin toView:self.view];
         }
         CGPoint relativePosition = component->_absolutePosition;
@@ -299,10 +306,11 @@ WX_EXPORT_METHOD(@selector(resetLoadmore))
 {
     UIScrollView *scrollView = (UIScrollView *)self.view;
     CGPoint contentOffset = scrollView.contentOffset;
+    CGFloat scaleFactor = self.weexInstance.pixelScaleFactor;
     
     if (_scrollDirection == WXScrollDirectionHorizontal) {
         CGFloat contentOffetX = [component.supercomponent.view convertPoint:component.view.frame.origin toView:self.view].x;
-        contentOffetX += offset * WXScreenResizeRadio();
+        contentOffetX += offset * scaleFactor;
         
         if (contentOffetX > scrollView.contentSize.width - scrollView.frame.size.width) {
             contentOffset.x = scrollView.contentSize.width - scrollView.frame.size.width;
@@ -311,7 +319,7 @@ WX_EXPORT_METHOD(@selector(resetLoadmore))
         }
     } else {
         CGFloat contentOffetY = [component.supercomponent.view convertPoint:component.view.frame.origin toView:self.view].y;
-        contentOffetY += offset * WXScreenResizeRadio();
+        contentOffetY += offset * scaleFactor;
         
         if (contentOffetY > scrollView.contentSize.height - scrollView.frame.size.height) {
             contentOffset.y = scrollView.contentSize.height - scrollView.frame.size.height;
@@ -325,7 +333,7 @@ WX_EXPORT_METHOD(@selector(resetLoadmore))
 
 - (BOOL)isNeedLoadMore
 {
-    if (_loadMoreOffset >= 0.0) {
+    if (_loadMoreOffset >= 0.0 && ((UIScrollView *)self.view).contentOffset.y >= 0) {
         return _previousLoadMoreContentHeight != ((UIScrollView *)self.view).contentSize.height && ((UIScrollView *)self.view).contentSize.height - ((UIScrollView *)self.view).contentOffset.y -  self.view.frame.size.height <= _loadMoreOffset;
     }
     
@@ -461,8 +469,6 @@ WX_EXPORT_METHOD(@selector(resetLoadmore))
     }
 }
 
-#pragma mark  Private Methods
-
 - (void)handleAppear
 {
     if (![self isViewLoaded]) {
@@ -481,6 +487,8 @@ WX_EXPORT_METHOD(@selector(resetLoadmore))
     }
 }
 
+#pragma mark  Private Methods
+
 - (void)scrollToTarget:(WXScrollToTarget *)target scrollRect:(CGRect)rect
 {
     WXComponent *component = target.target;

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Component/WXSliderComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXSliderComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXSliderComponent.m
index 99a4c6f..6ad82ff 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXSliderComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/WXSliderComponent.m
@@ -18,6 +18,7 @@
 
 @protocol WXSliderViewDelegate <UIScrollViewDelegate>
 
+- (void)sliderView:(WXSliderView *)sliderView sliderViewDidScroll:(UIScrollView *)scrollView;
 - (void)sliderView:(WXSliderView *)sliderView didScrollToItemAtIndex:(NSInteger)index;
 
 @end
@@ -284,6 +285,9 @@
     if (itemView) {
         self.currentIndex = itemView.tag;
     }
+    if (self.delegate && [self.delegate respondsToSelector:@selector(sliderView:sliderViewDidScroll:)]) {
+        [self.delegate sliderView:self sliderViewDidScroll:self.scrollView];
+    }
 }
 
 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
@@ -310,8 +314,12 @@
 @property (nonatomic, assign) BOOL  autoPlay;
 @property (nonatomic, assign) NSUInteger interval;
 @property (nonatomic, assign) NSInteger index;
+@property (nonatomic, assign) CGFloat lastOffsetXRatio;
+@property (nonatomic, assign) CGFloat offsetXAccuracy;
 @property (nonatomic, assign) BOOL  sliderChangeEvent;
+@property (nonatomic, assign) BOOL  sliderScrollEvent;
 @property (nonatomic, strong) NSMutableArray *childrenView;
+@property (nonatomic, assign) BOOL scrollable;
 
 @end
 
@@ -326,8 +334,10 @@
 {
     if (self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]) {
         _sliderChangeEvent = NO;
+        _sliderScrollEvent = NO;
         _interval = 3000;
         _childrenView = [NSMutableArray new];
+        _lastOffsetXRatio = 0;
         
         if (attributes[@"autoPlay"]) {
             _autoPlay = [attributes[@"autoPlay"] boolValue];
@@ -341,6 +351,12 @@
             _index = [attributes[@"index"] integerValue];
         }
         
+        _scrollable = attributes[@"scrollable"] ? [WXConvert BOOL:attributes[@"scrollable"]] : YES;
+
+        if (attributes[@"offsetXAccuracy"]) {
+            _offsetXAccuracy = [WXConvert CGFloat:attributes[@"offsetXAccuracy"]];
+        }
+        
         self.cssNode->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
     }
     return self;
@@ -359,6 +375,7 @@
     _sliderView.delegate = self;
     _sliderView.scrollView.pagingEnabled = YES;
     _sliderView.exclusiveTouch = YES;
+    _sliderView.scrollView.scrollEnabled = _scrollable;
     
     if (_autoPlay) {
         [self _startAutoPlayTimer];
@@ -465,6 +482,15 @@
         self.currentIndex = _index;
         [_sliderView scroll2ItemView:self.currentIndex animated:YES];
     }
+    
+    if (attributes[@"scrollable"]) {
+        _scrollable = attributes[@"scrollable"] ? [WXConvert BOOL:attributes[@"scrollable"]] : YES;
+        ((WXSliderView *)self.view).scrollView.scrollEnabled = _scrollable;
+    }
+    
+    if (attributes[@"offsetXAccuracy"]) {
+        _offsetXAccuracy = [WXConvert CGFloat:attributes[@"offsetXAccuracy"]];
+    }
 }
 
 - (void)addEvent:(NSString *)eventName
@@ -472,6 +498,9 @@
     if ([eventName isEqualToString:@"change"]) {
         _sliderChangeEvent = YES;
     }
+    if ([eventName isEqualToString:@"scroll"]) {
+        _sliderScrollEvent = YES;
+    }
 }
 
 - (void)removeEvent:(NSString *)eventName
@@ -479,6 +508,9 @@
     if ([eventName isEqualToString:@"change"]) {
         _sliderChangeEvent = NO;
     }
+    if ([eventName isEqualToString:@"scroll"]) {
+        _sliderScrollEvent = NO;
+    }
 }
 
 #pragma mark Public Methods
@@ -530,10 +562,24 @@
     }
 }
 
+#pragma mark ScrollView Delegate
+
+- (void)sliderView:(WXSliderView *)sliderView sliderViewDidScroll:(UIScrollView *)scrollView
+{
+    if (_sliderScrollEvent) {
+        CGFloat width = scrollView.frame.size.width;
+        CGFloat XDeviation = scrollView.frame.origin.x - (scrollView.contentOffset.x - width);
+        CGFloat offsetXRatio = (XDeviation / width);
+        if (ABS(offsetXRatio - _lastOffsetXRatio) >= _offsetXAccuracy) {
+            _lastOffsetXRatio = offsetXRatio;
+            [self fireEvent:@"scroll" params:@{@"offsetXRatio":[NSNumber numberWithFloat:offsetXRatio]} domChanges:nil];
+        }
+    }
+}
+
 - (void)sliderView:(WXSliderView *)sliderView didScrollToItemAtIndex:(NSInteger)index
 {
     self.currentIndex = index;
-    
     if (_sliderChangeEvent) {
         [self fireEvent:@"change" params:@{@"index":@(index)} domChanges:@{@"attrs": @{@"index": @(index)}}];
     }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b5123119/ios/sdk/WeexSDK/Sources/Component/WXSliderNeighborComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXSliderNeighborComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXSliderNeighborComponent.m
index b3ec0de..d7b3203 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXSliderNeighborComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/WXSliderNeighborComponent.m
@@ -114,7 +114,7 @@
     self.isAccessibilityElement = YES;
     
     [self addSubview:_contentView];
-     
+    
     if (_dataSource) {
         [self reloadData];
     }
@@ -514,6 +514,23 @@ NSComparisonResult sliderNeighorCompareViewDepth(UIView *view1, UIView *view2, W
     return YES;
 }
 
+- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
+   //if the view which the otherGestureRecognizer works on is a scrollview and also it is scrollEnabled vertically ,at this time,we should not block the guesture from being recognized by the otherGestureRecognize
+    if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && [otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) {
+        if ([otherGestureRecognizer.view isKindOfClass:[UIScrollView class]]) {
+            UIScrollView* scrollview = (UIScrollView *)otherGestureRecognizer.view;
+            if (scrollview.scrollEnabled) {
+                UIPanGestureRecognizer* panRcgn= (UIPanGestureRecognizer *)gestureRecognizer;
+                //check offset for confirming vertival movement
+                if (fabs([panRcgn translationInView:panRcgn.view].y) > fabs([panRcgn translationInView:panRcgn.view].x)*16) {
+                    return YES;
+                }
+            }
+        }
+    }
+    return NO;
+}
+
 
 - (void)didPan:(UIPanGestureRecognizer *)panGesture
 {
@@ -1364,7 +1381,9 @@ NSComparisonResult sliderNeighorCompareViewDepth(UIView *view1, UIView *view2, W
     WXPixelType neighborSpace;
     CGFloat neighborAlpha;
     CGFloat neighborScale;
+    CGFloat currentItemScale;
 }
+
 @property (nonatomic, strong) WXSliderNeighborView *sliderView;
 @property (nonatomic, assign) BOOL  autoPlay;
 @property (nonatomic, assign) NSUInteger interval;
@@ -1374,43 +1393,33 @@ NSComparisonResult sliderNeighorCompareViewDepth(UIView *view1, UIView *view2, W
 @property (nonatomic, assign) BOOL  sliderChangeEvent;
 @property (nonatomic, assign) NSInteger currentIndex;
 @property (nonatomic) CGRect itemRect;
+@property (nonatomic, assign) BOOL scrollable;
+
 @end
 
+#define DEFAULT_NEIGHBOR_ITEM_SCALE 0.8
+#define DEFAULT_CURRENT_ITEM_SCALE 0.9
+#define DEFAULT_NEIGHBOR_ALPHA 0.6
+#define DEFAULT_ANIMATION_DURATION 0.3
+#define DEFAULT_NEIGHBOR_SPACE 25
+
+
 @implementation WXSliderNeighborComponent
 
 - (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDictionary *)styles attributes:(NSDictionary *)attributes events:(NSArray *)events weexInstance:(WXSDKInstance *)weexInstance {
     if (self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]) {
         _sliderChangeEvent = NO;
-        _sliderView = [[WXSliderNeighborView alloc] init];
-        _sliderView.delegate = self;
-        _sliderView.dataSource = self;
         _interval = 3000;
-        [self setNeighborSpace:attributes];
-        [self setNeighborAlpha:attributes];
-        [self setNeighborScale:attributes];
         _items = [NSMutableArray array];
         _itemRect = CGRectNull;
-        
-        if (attributes[@"autoPlay"]) {
-            _autoPlay = [attributes[@"autoPlay"] boolValue];
-        }
-
-        if (attributes[@"interval"]) {
-            _interval = [attributes[@"interval"] integerValue];
-        }
-
-        if (attributes[@"index"]) {
-            _index = [attributes[@"index"] integerValue];
-            _currentIndex = _index;
-        }
-        if (attributes[@"autoPlay"]) {
-            _autoPlay = [attributes[@"autoPlay"] boolValue];
-        }
-
-        if (attributes[@"interval"]) {
-            _interval = [attributes[@"interval"] integerValue];
-        }
+        self->neighborAlpha = DEFAULT_NEIGHBOR_ALPHA;
+        self->neighborScale = DEFAULT_NEIGHBOR_ITEM_SCALE;
+        self->currentItemScale = DEFAULT_CURRENT_ITEM_SCALE;
+        self->neighborSpace = [WXConvert WXPixelType:@(DEFAULT_NEIGHBOR_SPACE) scaleFactor:self.weexInstance.pixelScaleFactor];
+        _scrollable = YES;
+        [self setAttributes:attributes];
     
+        _scrollable = attributes[@"scrollable"] ? [WXConvert BOOL:attributes[@"scrollable"]] : YES;
     }
     self.cssNode->style.flex_direction = CSS_FLEX_DIRECTION_ROW;
     
@@ -1422,15 +1431,33 @@ NSComparisonResult sliderNeighorCompareViewDepth(UIView *view1, UIView *view2, W
 
 - (UIView *)loadView
 {
+    _sliderView = [[WXSliderNeighborView alloc] init];
     return _sliderView;
 }
 
+- (void)dealloc
+{
+    _sliderView.delegate = nil;
+    _sliderView.dataSource = nil;
+    if (_autoPlay) {
+        [self _stopAutoPlayTimer];
+    }
+    _sliderView = nil;
+    [self.items removeAllObjects];
+}
+
+- (void)viewDidUnload
+{
+    [self.items removeAllObjects];
+}
+
 - (void)viewDidLoad
 {
     _sliderView = (WXSliderNeighborView *)self.view;
     _sliderView.delegate = self;
     _sliderView.dataSource = self;
     _sliderView.contentView.clipsToBounds = YES;
+    _sliderView.scrollEnabled = _scrollable;
     if (_autoPlay) {
         [self _startAutoPlayTimer];
     } else {
@@ -1491,7 +1518,7 @@ NSComparisonResult sliderNeighorCompareViewDepth(UIView *view1, UIView *view2, W
 }
 
 #pragma mark attributes update
-- (void)updateAttributes:(NSDictionary *)attributes
+- (void)setAttributes:(NSDictionary *)attributes
 {
     if (attributes[@"index"]) {
         _index = [attributes[@"index"] integerValue];
@@ -1505,7 +1532,6 @@ NSComparisonResult sliderNeighorCompareViewDepth(UIView *view1, UIView *view2, W
             [self _stopAutoPlayTimer];
         }
     }
-    
     if (attributes[@"interval"]) {
         _interval = [attributes[@"interval"] integerValue];
         
@@ -1518,14 +1544,24 @@ NSComparisonResult sliderNeighorCompareViewDepth(UIView *view1, UIView *view2, W
     if (attributes[@"neighborScale"]) {
         [self setNeighborScale:attributes];
     }
+    if (attributes[@"currentItemScale"]) {
+        [self setCurrentItemScale:attributes];
+    }
     if (attributes[@"neighborAlpha"]) {
         [self setNeighborAlpha:attributes];
     }
-    
     if (attributes[@"neighborSpace"]) {
         [self setNeighborSpace:attributes];
     }
-    
+    if (attributes[@"scrollable"]) {
+        _scrollable = attributes[@"scrollable"] ? [WXConvert BOOL:attributes[@"scrollable"]] : YES;
+        ((WXSliderNeighborView *)self.view).scrollEnabled = _scrollable;
+    }
+}
+
+- (void)updateAttributes:(NSDictionary *)attributes
+{
+    [self setAttributes:attributes];
     [self.sliderView setCurrentItemIndex:_index];
     [self updateSliderPage:YES];
 }
@@ -1558,9 +1594,7 @@ NSComparisonResult sliderNeighorCompareViewDepth(UIView *view1, UIView *view2, W
 
 - (void)setNeighborSpace:(NSDictionary *)attributes{
     if(attributes[@"neighborSpace"]) {
-        self->neighborSpace = [WXConvert WXPixelType:attributes[@"neighborSpace"]];
-    } else {
-        self->neighborSpace = [WXConvert WXPixelType:@(25)];
+        self->neighborSpace = [WXConvert WXPixelType:attributes[@"neighborSpace"] scaleFactor:self.weexInstance.pixelScaleFactor];
     }
 }
 
@@ -1569,8 +1603,14 @@ NSComparisonResult sliderNeighorCompareViewDepth(UIView *view1, UIView *view2, W
         self->neighborAlpha = [WXConvert CGFloat:attributes[@"neighborAlpha"]];
         self->neighborAlpha = self->neighborAlpha >= 0 ? self->neighborAlpha : 0;
         self->neighborAlpha = self->neighborAlpha <= 1 ? self->neighborAlpha: 1;
-    } else {
-        self->neighborAlpha = 0.6;
+    }
+}
+
+- (void)setCurrentItemScale:(NSDictionary *)attributes {
+    if (attributes[@"currentItemScale"]) {
+        self->currentItemScale = [WXConvert CGFloat:attributes[@"currentItemScale"]];
+        self->currentItemScale = self->currentItemScale >= 0 ? self->currentItemScale : 0;
+        self->currentItemScale = self->currentItemScale <= 1 ? self->currentItemScale: 1;
     }
 }
 
@@ -1580,9 +1620,6 @@ NSComparisonResult sliderNeighorCompareViewDepth(UIView *view1, UIView *view2, W
         self->neighborScale = [WXConvert CGFloat:attributes[@"neighborScale"]];
         self->neighborScale = self->neighborScale >= 0? self->neighborScale : 0;
         self->neighborScale = self->neighborScale <= 1? self->neighborScale :1;
-        
-    } else {
-        self->neighborScale = 0.8;
     }
 }
 
@@ -1639,7 +1676,11 @@ NSComparisonResult sliderNeighorCompareViewDepth(UIView *view1, UIView *view2, W
 - (UIView *)sliderNeighbor:(WXSliderNeighborView *)sliderNeighbor viewForItemAtIndex:(NSInteger)index reusingView:(UIView *)view {
     
     if (!view) {
-        view = self.items[index];
+        if (index < [self.items count]) {
+            view = self.items[index];
+        }else {
+            return nil;
+        }
     } else {
         view.tag = 1;
     }
@@ -1700,7 +1741,7 @@ NSComparisonResult sliderNeighorCompareViewDepth(UIView *view1, UIView *view2, W
     float duration = 0;
     __weak typeof(self) weakSelf = self;
     if (animate) {
-        duration = 0.3;
+        duration = DEFAULT_ANIMATION_DURATION;
     }
     
     [UIView animateWithDuration:duration animations:^{
@@ -1708,14 +1749,13 @@ NSComparisonResult sliderNeighorCompareViewDepth(UIView *view1, UIView *view2, W
         if (strongSelf) {
             currentView.alpha = 1.0;
             
-            if (fabs(strongSelf->neighborScale - 0) > CGFLOAT_MIN) {
-                transfrom = CGAffineTransformConcat(transfrom,CGAffineTransformMakeScale(0.9, 0.9));
+            if (fabs(strongSelf->currentItemScale) > CGFLOAT_MIN) {
+                transfrom = CGAffineTransformConcat(transfrom,CGAffineTransformMakeScale(strongSelf->currentItemScale, strongSelf->currentItemScale));
             }
             currentView.transform = transfrom;
             transfrom = CGAffineTransformIdentity;
-            
-            if (fabs(strongSelf->neighborScale - 0) <= CGFLOAT_MIN) {
-                strongSelf->neighborScale = 0.8;
+            if (fabs(strongSelf->neighborScale) <= CGFLOAT_MIN) {
+                strongSelf->neighborScale = DEFAULT_NEIGHBOR_ITEM_SCALE;
             }
             
             CGFloat tx = 0.5*_itemRect.size.width*((1-self->neighborScale)+(1-0.9))-self->neighborSpace;