You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by ac...@apache.org on 2018/04/03 07:55:49 UTC

incubator-weex git commit: [WEEX-113] [iOS] New Touch Dispatch Mechanism And Bubble Sync Method

Repository: incubator-weex
Updated Branches:
  refs/heads/master caf74c6c1 -> eccc224ab


[WEEX-113] [iOS] New Touch Dispatch Mechanism And Bubble Sync Method

Now iOS support new events dispatch by stopPropagation. You can use @stopPropagation to decide if touch event or other advanced gesture events to pass down.

You can try this feature by http://dotwe.org/vue/10a573183dfe3ba172c818e6d285f729 or http://dotwe.org/vue/359e12259ab86d410cb32cda9264e62c.

[WEEX-113] [iOS] New Touch Dispatch Mechanism And Bubble Sync Method

[WEEX-113] [iOS] New Touch Dispatch Mechanism And Bubble Sync Method

close #1093

[WEEX-113] [iOS] New Touch Dispatch Mechanism And Bubble Sync Method


Project: http://git-wip-us.apache.org/repos/asf/incubator-weex/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-weex/commit/eccc224a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-weex/tree/eccc224a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-weex/diff/eccc224a

Branch: refs/heads/master
Commit: eccc224ab2195b14cd42f38d52ef64a774b9d6aa
Parents: caf74c6
Author: doumafang <do...@gmail.com>
Authored: Thu Mar 29 14:45:39 2018 +0800
Committer: acton393 <zh...@gmail.com>
Committed: Tue Apr 3 15:55:01 2018 +0800

----------------------------------------------------------------------
 .../WeexSDK/Sources/Bridge/WXBridgeContext.h    |   4 +
 .../WeexSDK/Sources/Bridge/WXBridgeContext.m    |   8 +-
 .../RecycleList/WXRecycleListComponent.m        |  13 ++-
 .../Sources/Component/WXComponent_internal.h    |   2 +
 .../WeexSDK/Sources/Component/WXListComponent.m |   5 +
 .../Sources/Component/WXScrollerComponent.h     |   2 +-
 .../Sources/Component/WXScrollerComponent.m     |  16 ++-
 .../WeexSDK/Sources/Events/WXComponent+Events.h |  36 +++++-
 .../WeexSDK/Sources/Events/WXComponent+Events.m | 113 +++++++++++++++----
 .../WeexSDK/Sources/Manager/WXBridgeManager.h   |   3 +
 .../WeexSDK/Sources/Manager/WXBridgeManager.m   |  41 ++++++-
 .../Sources/Protocol/WXScrollerProtocol.h       |   3 +
 12 files changed, 211 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/eccc224a/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 b3b66b6..5f6259a 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.h
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.h
@@ -19,6 +19,7 @@
 
 #import <Foundation/Foundation.h>
 #import <JavaScriptCore/JavaScriptCore.h>
+#import "WXBridgeProtocol.h"
 
 @class WXCallJSMethod;
 @class WXSDKInstance;
@@ -80,6 +81,9 @@
  *  @param method    :   object of bridge method
  **/
 - (void)executeJsMethod:(WXCallJSMethod *)method;
+
+- (JSValue *)excuteJSMethodWithResult:(WXCallJSMethod *)method;
+
 /**
  *  Register Modules Method
  *  @param modules   :   module list

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/eccc224a/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 af473cf..07803ce 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
@@ -18,7 +18,6 @@
  */
 
 #import "WXBridgeContext.h"
-#import "WXBridgeProtocol.h"
 #import "WXJSCoreBridge.h"
 #import "WXLog.h"
 #import "WXUtility.h"
@@ -584,6 +583,12 @@ _Pragma("clang diagnostic pop") \
     }
 }
 
+- (JSValue *)excuteJSMethodWithResult:(WXCallJSMethod *)method
+{
+    WXAssertBridgeThread();
+    return  [self.jsBridge callJSMethod:@"callJS" args:@[method.instance.instanceId, @[[method callJSTask]]]];
+}
+
 - (void)executeAllJsService
 {
     for(NSDictionary *service in _jsServiceQueue) {
@@ -692,7 +697,6 @@ _Pragma("clang diagnostic pop") \
             for(WXCallJSMethod *method in sendQueue){
                 [tasks addObject:[method callJSTask]];
             }
-            
             [sendQueue removeAllObjects];
             execIns = instance;
             break;

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/eccc224a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.m b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.m
index a98119f..dd0556a 100644
--- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.m
@@ -33,6 +33,17 @@
 #import "WXSDKManager.h"
 #import "WXComponent+DataBinding.h"
 
+@interface WXRecycleListComponentView:UICollectionView
+@end
+
+@implementation WXRecycleListComponentView
+- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
+{
+    return [self.wx_component requestGestureShouldStopPropagation:gestureRecognizer shouldReceiveTouch:touch];
+}
+
+@end
+
 @interface WXRecycleListComponent () <WXRecycleListLayoutDelegate, WXRecycleListUpdateDelegate, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource>
 
 @end
@@ -87,7 +98,7 @@ WX_EXPORT_METHOD(@selector(setListData:))
 - (UIView *)loadView
 {
     WXRecycleListLayout *layout = [self recycleListLayout];
-    return [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
+    return [[WXRecycleListComponentView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
 }
 
 - (void)viewDidLoad

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/eccc224a/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 c8c7b5b..bf54a91 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
+++ b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
@@ -99,6 +99,8 @@ typedef id (^WXDataBindingBlock)(NSDictionary *data, BOOL *needUpdate);
     BOOL _listenHorizontalPan;
     BOOL _listenVerticalPan;
     
+    BOOL _listenStopPropagation;
+    
     WXTouchGestureRecognizer* _touchGesture;
     
     /**

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/eccc224a/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 159f0a4..4b92306 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXListComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/WXListComponent.m
@@ -42,6 +42,11 @@
     return NO;
 }
 
+- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
+{
+    return [self.wx_component requestGestureShouldStopPropagation:gestureRecognizer shouldReceiveTouch:touch];
+}
+
 - (void)layoutSubviews
 {
     [super layoutSubviews];

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/eccc224a/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 db0c155..c7f5db7 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.h
+++ b/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.h
@@ -19,7 +19,7 @@
 
 #import "WXScrollerProtocol.h"
 #import "WXComponent.h"
-
+#import "WXComponent+Events.h"
 @interface WXScrollerComponent : WXComponent <WXScrollerProtocol, UIScrollViewDelegate>
 
 @property (nonatomic, copy) void (^onScroll)(UIScrollView *);

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/eccc224a/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 c6f13a1..deaa2c2 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.m
@@ -29,10 +29,14 @@
 #import "WXConfigCenterProtocol.h"
 #import "WXSDKEngine.h"
 
-@interface WXScrollerComponnetView:UIScrollView
+@interface WXScrollerComponentView:UIScrollView
 @end
 
-@implementation WXScrollerComponnetView
+@implementation WXScrollerComponentView
+- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
+{
+    return [self.wx_component requestGestureShouldStopPropagation:gestureRecognizer shouldReceiveTouch:touch];
+}
 @end
 
 @interface WXScrollToTarget : NSObject
@@ -168,14 +172,14 @@ WX_EXPORT_METHOD(@selector(resetLoadmore))
 
 - (UIView *)loadView
 {
-    return [[WXScrollerComponnetView alloc] init];
+    return [[WXScrollerComponentView alloc] init];
 }
 
 - (void)viewDidLoad
 {
     [super viewDidLoad];
     [self setContentSize:_contentSize];
-    WXScrollerComponnetView* scrollView = (WXScrollerComponnetView *)self.view;
+    WXScrollerComponentView* scrollView = (WXScrollerComponentView *)self.view;
     scrollView.delegate = self;
     scrollView.exclusiveTouch = YES;
     scrollView.autoresizesSubviews = NO;
@@ -549,6 +553,10 @@ WX_EXPORT_METHOD(@selector(resetLoadmore))
 {
     return _refreshType;
 }
+- (BOOL)requestGestureShouldStopPropagation:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
+{
+    return [self gestureShouldStopPropagation:gestureRecognizer shouldReceiveTouch:touch];
+}
 
 #pragma mark UIScrollViewDelegate
 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/eccc224a/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.h b/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.h
index 00500da..806b17d 100644
--- a/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.h
+++ b/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.h
@@ -18,7 +18,41 @@
  */
 
 #import "WXComponent.h"
+#import <objc/runtime.h>
 
-@interface WXComponent (Events) <UIGestureRecognizerDelegate>
+@interface UITouch (WXTouchGestureRecognizer)
+
+@property (nonatomic, strong) NSNumber *wx_identifier;
+@property (nonatomic, strong) NSNumber *wx_stopPropagation;
+
+@end
+
+@implementation UITouch (WXTouchGestureRecognizer)
+
+- (NSNumber *)wx_identifier
+{
+    return objc_getAssociatedObject(self, _cmd);
+}
+
+- (void)setWx_identifier:(NSNumber *)wx_identifier
+{
+    objc_setAssociatedObject(self, @selector(wx_identifier), wx_identifier, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
 
+- (NSNumber *)wx_stopPropagation
+{
+    return objc_getAssociatedObject(self, _cmd);
+}
+
+- (void)setWx_stopPropagation:(NSNumber *)wx_stopPropagation
+{
+    objc_setAssociatedObject(self, @selector(wx_stopPropagation), wx_stopPropagation, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+@end
+
+
+@interface WXComponent (Events) <UIGestureRecognizerDelegate>
+- (BOOL)gestureShouldStopPropagation:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;
+- (BOOL)requestGestureShouldStopPropagation:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;
 @end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/eccc224a/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m b/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m
index 2ea93d9..2ad7503 100644
--- a/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m
+++ b/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m
@@ -29,33 +29,12 @@
 #import "WXDefine.h"
 #import "WXRecycleListComponent.h"
 #import "WXRecycleListDataManager.h"
-
 #import <objc/runtime.h>
 #import <UIKit/UIGestureRecognizerSubclass.h>
 #import "WXComponent+PseudoClassManagement.h"
 
 #pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
 
-@interface UITouch (WXTouchGestureRecognizer)
-
-@property (nonatomic, strong) NSNumber *wx_identifier;
-
-@end
-
-@implementation UITouch (WXTouchGestureRecognizer)
-
-- (NSNumber *)wx_identifier
-{
-    return objc_getAssociatedObject(self, _cmd);
-}
-
-- (void)setWx_identifier:(NSNumber *)wx_identifier
-{
-    objc_setAssociatedObject(self, @selector(wx_identifier), wx_identifier, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
-}
-
-@end
-
 @interface UIGestureRecognizer (WXGesture)
 
 @property (nonatomic, strong) NSNumber *wx_identifier;
@@ -95,6 +74,44 @@
 
 @end
 
+@interface WXEventManager :NSObject
++ (instancetype) sharedManager;
+- (BOOL)stopPropagation:(NSString *)instanceId ref:(NSString *)ref type:(NSString *)type params:(NSDictionary *)params;
+@end
+
+@implementation WXEventManager
+
+- (instancetype) init
+{
+    self = [super init];
+    if (self) {
+        
+    }
+    return self;
+}
+
++ (instancetype)sharedManager
+{
+    static id _sharedInstance = nil;
+    static dispatch_once_t oncePredicate;
+    dispatch_once(&oncePredicate, ^{
+        _sharedInstance = [[self alloc] init];
+    });
+    return _sharedInstance;
+}
+
+- (BOOL)stopPropagation:(NSString *)instanceId ref:(NSString *)ref type:(NSString *)type params:(NSDictionary *)params
+{
+    JSValue *value = [[WXSDKManager bridgeMgr] fireEventWithResult:instanceId ref:ref type:type params:params domChanges:nil];
+    
+    if ([value.toString isEqualToString:@"true"]) {
+        return YES;
+    }
+    return NO;
+}
+
+@end
+
 @implementation WXComponent (Events)
 
 #pragma mark Public
@@ -192,6 +209,8 @@ if ([removeEventName isEqualToString:@#eventName]) {\
     WX_ADD_EVENT(touchcancel, addTouchCancelEvent)
     WX_ADD_EVENT(accessibilityMagicTap, addAccessibilityMagicTapEvent)
     
+    WX_ADD_EVENT(stopPropagation, addStopPropagationEvent)
+    
     if(_isListenPseudoTouch) {
         self.touchGesture.listenPseudoTouch = YES;
     }
@@ -220,6 +239,9 @@ if ([removeEventName isEqualToString:@#eventName]) {\
     WX_REMOVE_EVENT(touchend, removeTouchEndEvent)
     WX_REMOVE_EVENT(touchcancel, removeTouchCancelEvent)
     WX_REMOVE_EVENT(accessibilityMagicTap, removeAccessibilityMagicTapEvent)
+    
+    WX_REMOVE_EVENT(stopPropagation, removeStopPropagationEvent)
+    
     if(_isListenPseudoTouch) {
         self.touchGesture.listenPseudoTouch = NO;
     }
@@ -290,6 +312,20 @@ if ([removeEventName isEqualToString:@#eventName]) {\
     _accessibilityMagicTapEvent = NO;
 }
 
+#pragma mark - StopPropagation
+
+- (void)addStopPropagationEvent
+{
+    _listenStopPropagation = YES;
+    self.touchGesture.listenTouchMove = YES;
+}
+
+- (void)removeStopPropagationEvent
+{
+    _listenStopPropagation = NO;
+    self.touchGesture.listenTouchMove = NO;
+}
+
 #pragma mark - Click Event
 
 - (void)addClickEvent
@@ -335,7 +371,6 @@ if ([removeEventName isEqualToString:@#eventName]) {\
         position[@"width"] = @(frame.size.width/scaleFactor);
         position[@"height"] = @(frame.size.height/scaleFactor);
     }
-
     [self fireEvent:@"click" params:@{@"position":position}];
 }
 
@@ -637,7 +672,6 @@ if ([removeEventName isEqualToString:@#eventName]) {\
         _touchGesture.delegate = self;
         [self.view addGestureRecognizer:_touchGesture];
     }
-    
     return _touchGesture;
 }
 
@@ -698,11 +732,40 @@ if ([removeEventName isEqualToString:@#eventName]) {\
     }
 }
 
-#pragma mark - UIGestureRecognizerDelegate
+- (BOOL)gestureShouldStopPropagation:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
+{
+    if(touch.wx_stopPropagation && [touch.wx_stopPropagation isEqualToNumber:@1]){
+        return NO;
+    }
+    else
+    {
+        if (_listenStopPropagation)
+        {
+            NSString *ref = _templateComponent ? _templateComponent.ref : self.ref;
+            CGPoint screenLocation = [touch locationInView:touch.window];
+            CGPoint pageLocation = [touch locationInView:self.weexInstance.rootView];
+            NSDictionary *resultTouch = [self touchResultWithScreenLocation:screenLocation pageLocation:pageLocation identifier:touch.wx_identifier];
+            NSString *touchState;
+            if (touch.phase == UITouchPhaseBegan) {
+                touchState = @"start";
+            }
+            else if (touch.phase == UITouchPhaseMoved){
+                touchState = @"move";
+            }
+            else{
+                touchState = @"end";
+            }
+            BOOL stopPropagation = [[WXEventManager sharedManager]stopPropagation:self.weexInstance.instanceId ref:ref type:@"stopPropagation" params:@{@"changedTouches":resultTouch ? @[resultTouch] : @[],@"action":touchState}];
+            touch.wx_stopPropagation = stopPropagation ? @1 : @0;
+        }
+    }
+    return YES;
+}
 
+#pragma mark - UIGestureRecognizerDelegate
 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
 {
-    return YES;
+    return [self gestureShouldStopPropagation:gestureRecognizer shouldReceiveTouch:touch];
 }
 
 - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/eccc224a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h
index 9d7cece..088d601 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h
@@ -19,6 +19,7 @@
 
 #import <Foundation/Foundation.h>
 #import <JavaScriptCore/JavaScriptCore.h>
+#import "WXBridgeContext.h"
 
 @class WXBridgeMethod;
 @class WXSDKInstance;
@@ -142,6 +143,8 @@ extern void WXPerformBlockOnBridgeThread(void (^block)(void));
  **/
 - (void)fireEvent:(NSString *)instanceId ref:(NSString *)ref type:(NSString *)type params:(NSDictionary *)params domChanges:(NSDictionary *)domChanges handlerArguments:(NSArray *)handlerArguments;
 
+- (JSValue *)fireEventWithResult:(NSString *)instanceId ref:(NSString *)ref type:(NSString *)type params:(NSDictionary *)params domChanges:(NSDictionary *)domChanges;
+
 /**
  * componentHook
  * @param instanceId  : instance id

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/eccc224a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
index c77bdde..37fb14c 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
@@ -18,7 +18,6 @@
  */
 
 #import "WXBridgeManager.h"
-#import "WXBridgeContext.h"
 #import "WXLog.h"
 #import "WXAssert.h"
 #import "WXBridgeMethod.h"
@@ -127,6 +126,23 @@ void WXPerformBlockOnBridgeThread(void (^block)(void))
     }
 }
 
+void WXPerformBlockSyncOnBridgeThread(void (^block) (void))
+{
+    [WXBridgeManager _performBlockSyncOnBridgeThread:block];
+}
+
++ (void)_performBlockSyncOnBridgeThread:(void (^)(void))block
+{
+    if ([NSThread currentThread] == [self jsThread]) {
+        block();
+    } else {
+        [self performSelector:@selector(_performBlockSyncOnBridgeThread:)
+                     onThread:[self jsThread]
+                   withObject:[block copy]
+                waitUntilDone:YES];
+    }
+}
+
 #pragma mark JSBridge Management
 
 - (void)createInstance:(NSString *)instance
@@ -230,6 +246,17 @@ void WXPerformBlockOnBridgeThread(void (^block)(void))
     });
 }
 
+- (JSValue *)callJSMethodWithResult:(WXCallJSMethod *)method
+{
+    if (!method) return nil;
+    __weak typeof(self) weakSelf = self;
+    __block JSValue *value;
+    WXPerformBlockSyncOnBridgeThread(^(){
+        value = [weakSelf.bridgeCtx excuteJSMethodWithResult:method];
+    });
+    return value;
+}
+
 -(void)registerService:(NSString *)name withServiceUrl:(NSURL *)serviceScriptUrl withOptions:(NSDictionary *)options
 {
     if (!name || !serviceScriptUrl || !options) return;
@@ -340,6 +367,18 @@ void WXPerformBlockOnBridgeThread(void (^block)(void))
     });
 }
 
+- (JSValue *)fireEventWithResult:(NSString *)instanceId ref:(NSString *)ref type:(NSString *)type params:(NSDictionary *)params domChanges:(NSDictionary *)domChanges
+{
+    if (!type || !ref) {
+        WXLogError(@"Event type and component ref should not be nil");
+        return nil;
+    }
+    NSArray *args = @[ref, type, params?:@{}, domChanges?:@{}];
+    WXSDKInstance *instance = [WXSDKManager instanceForID:instanceId];
+    WXCallJSMethod *method = [[WXCallJSMethod alloc] initWithModuleName:nil methodName:@"fireEvent" arguments:args instance:instance];
+    return [self callJSMethodWithResult:method];
+}
+
 - (void)callBack:(NSString *)instanceId funcId:(NSString *)funcId params:(id)params keepAlive:(BOOL)keepAlive
 {
     NSArray *args = nil;

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/eccc224a/ios/sdk/WeexSDK/Sources/Protocol/WXScrollerProtocol.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Protocol/WXScrollerProtocol.h b/ios/sdk/WeexSDK/Sources/Protocol/WXScrollerProtocol.h
index 86ec39d..81b5984 100644
--- a/ios/sdk/WeexSDK/Sources/Protocol/WXScrollerProtocol.h
+++ b/ios/sdk/WeexSDK/Sources/Protocol/WXScrollerProtocol.h
@@ -72,6 +72,9 @@
 
 - (WXScrollDirection)scrollDirection;
 
+@optional
 - (NSString*)refreshType;
+
+- (BOOL)requestGestureShouldStopPropagation:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;
 @end