http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b77b4259/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 b76ac90..e50e15a 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m
@@ -136,6 +136,9 @@ _Pragma("clang diagnostic pop") \
         }
         [WXTracingManager startTracingWithInstanceId:instanceId 
ref:elementData[@"ref"] className:nil name:WXTJSCall phase:WXTracingEnd 
functionName:@"addElement" options:nil];
         WXPerformBlockOnComponentThread(^{
+#ifdef DEBUG
+            WXLogDebug(@"flexLayout -> action: addElement : 
%@",elementData[@"type"]);
+#endif
             WXComponentManager *manager = instance.componentManager;
             if (!manager.isValid) {
                 return;
@@ -159,6 +162,9 @@ _Pragma("clang diagnostic pop") \
         }
         [WXTracingManager startTracingWithInstanceId:instanceId 
ref:bodyData[@"ref"] className:nil name:WXTJSCall phase:WXTracingEnd 
functionName:@"createBody" options:@{@"threadName":WXTJSBridgeThread}];
         WXPerformBlockOnComponentThread(^{
+#ifdef DEBUG
+            WXLogDebug(@"flexLayout -> action: createBody %@ 
ref:%@",bodyData[@"type"],bodyData[@"ref"]);
+#endif
             WXComponentManager *manager = instance.componentManager;
             if (!manager.isValid) {
                 return;
@@ -183,6 +189,9 @@ _Pragma("clang diagnostic pop") \
         }
         [WXTracingManager startTracingWithInstanceId:instanceId ref:ref 
className:nil name:WXTJSCall phase:WXTracingEnd functionName:@"removeElement" 
options:nil];
         WXPerformBlockOnComponentThread(^{
+#ifdef DEBUG
+            WXLogDebug(@"flexLayout -> action: removeElement ref:%@",ref);
+#endif
             WXComponentManager *manager = instance.componentManager;
             if (!manager.isValid) {
                 return;
@@ -206,6 +215,9 @@ _Pragma("clang diagnostic pop") \
         }
         [WXTracingManager startTracingWithInstanceId:instanceId ref:ref 
className:nil name:WXTJSCall phase:WXTracingEnd functionName:@"moveElement" 
options:nil];
         WXPerformBlockOnComponentThread(^{
+#ifdef DEBUG
+            WXLogDebug(@"flexLayout -> action: moveElement ,ref:%@ to 
ref:%@",ref,parentRef);
+#endif
             WXComponentManager *manager = instance.componentManager;
             if (!manager.isValid) {
                 return;
@@ -228,6 +240,9 @@ _Pragma("clang diagnostic pop") \
         
         [WXTracingManager startTracingWithInstanceId:instanceId ref:ref 
className:nil name:WXTJSCall phase:WXTracingEnd functionName:@"updateAttrs" 
options:@{@"threadName":WXTJSBridgeThread}];
         WXPerformBlockOnComponentThread(^{
+#ifdef DEBUG
+            WXLogDebug(@"flexLayout -> action: updateAttrs 
ref:%@,attr:%@",ref,attrsData);
+#endif
             WXComponentManager *manager = instance.componentManager;
             if (!manager.isValid) {
                 return;
@@ -251,6 +266,10 @@ _Pragma("clang diagnostic pop") \
         }
         [WXTracingManager startTracingWithInstanceId:instanceId ref:ref 
className:nil name:WXTJSCall phase:WXTracingEnd functionName:@"updateStyles" 
options:@{@"threadName":WXTJSBridgeThread}];
         WXPerformBlockOnComponentThread(^{
+            
+#ifdef DEBUG
+            WXLogDebug(@"flexLayout -> action: updateStyles 
ref:%@,styles:%@",ref,stylesData);
+#endif
             WXComponentManager *manager = instance.componentManager;
             if (!manager.isValid) {
                 return;
@@ -273,6 +292,10 @@ _Pragma("clang diagnostic pop") \
         }
         
         WXPerformBlockOnComponentThread(^{
+#ifdef DEBUG
+            WXLogDebug(@"flexLayout -> action: addEvent ref:%@",ref);
+#endif
+            
             WXComponentManager *manager = instance.componentManager;
             if (!manager.isValid) {
                 return;
@@ -295,6 +318,9 @@ _Pragma("clang diagnostic pop") \
         }
         
         WXPerformBlockOnComponentThread(^{
+#ifdef DEBUG
+            WXLogDebug(@"flexLayout -> action :removeEvent ref:%@",ref);
+#endif
             WXComponentManager *manager = instance.componentManager;
             if (!manager.isValid) {
                 return;
@@ -317,6 +343,10 @@ _Pragma("clang diagnostic pop") \
         }
         [WXTracingManager startTracingWithInstanceId:instanceId ref:nil 
className:nil name:WXTJSCall phase:WXTracingEnd functionName:@"createFinish" 
options:@{@"threadName":WXTJSBridgeThread}];
         WXPerformBlockOnComponentThread(^{
+#ifdef DEBUG
+            WXLogDebug(@"flexLayout -> action: createFinish :%@",instanceId);
+#endif
+            
             WXComponentManager *manager = instance.componentManager;
             if (!manager.isValid) {
                 return;
@@ -339,6 +369,9 @@ _Pragma("clang diagnostic pop") \
             WXLogInfo(@"instance not found for callNativeModule:%@.%@, maybe 
already destroyed", moduleName, methodName);
             return nil;
         }
+#ifdef DEBUG
+        WXLogDebug(@"flexLayout -> action: callNativeModule : %@ . 
%@",moduleName,methodName);
+#endif
         NSMutableDictionary * newOptions = [options mutableCopy];
         NSMutableArray * newArguments = [arguments mutableCopy];
         
@@ -367,6 +400,11 @@ _Pragma("clang diagnostic pop") \
     }];
     
     [_jsBridge registerCallNativeComponent:^void(NSString *instanceId, 
NSString *componentRef, NSString *methodName, NSArray *args, NSDictionary 
*options) {
+       
+#ifdef DEBUG
+        WXLogDebug(@"flexLayout -> action: callNativeComponent 
ref:%@",componentRef);
+#endif
+        
         WXSDKInstance *instance = [WXSDKManager instanceForID:instanceId];
         WXComponentMethod *method = [[WXComponentMethod alloc] 
initWithComponentRef:componentRef methodName:methodName arguments:args 
instance:instance];
         [method invoke];

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b77b4259/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.m
----------------------------------------------------------------------
diff --git 
a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.m 
b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.m
deleted file mode 100644
index a6adec0..0000000
--- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.m
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#import "WXCellSlotComponent.h"
-#import "WXComponent_internal.h"
-#import "WXComponentManager.h"
-#import "WXSDKInstance_private.h"
-#import "WXConvert.h"
-#import "WXAssert.h"
-#import "WXScrollerComponent.h"
-
-@implementation WXCellSlotComponent
-
-- (instancetype)initWithRef:(NSString *)ref
-                       type:(NSString *)type
-                     styles:(NSDictionary *)styles
-                 attributes:(NSDictionary *)attributes
-                     events:(NSArray *)events
-               weexInstance:(WXSDKInstance *)weexInstance
-{
-    self = [super initWithRef:ref type:type styles:styles 
attributes:attributes events:events weexInstance:weexInstance];
-    if (self) {
-        // TODO: isRecycle / insertAnimation / deleteAnimation / 
keepScrollPosition
-        if (attributes[@"default"]) {
-            _templateCaseType = @"default";
-        }
-        _templateCaseType = attributes[@"case"] ? [WXConvert 
NSString:attributes[@"case"]] : WXDefaultRecycleTemplateType;
-        _lazyCreateView = YES;
-        _isNeedJoinLayoutSystem = NO;
-    }
-    
-    return self;
-}
-
-- (void)updateAttributes:(NSDictionary *)attributes
-{
-    
-}
-
-- (void)updateCellData:(NSDictionary *)data
-{
-    WXAssertComponentThread();    
-    
-    [self updateBindingData:data];
-    [self triggerLayout];
-}
-
-- (void)_didInserted
-{
-    [self triggerLayout];
-}
-
-- (void)triggerLayout
-{
-    WXAssertComponentThread();
-    
-    //TODO: _isUseContainerWidth?
-    if (isUndefined(self.cssNode->style.dimensions[CSS_WIDTH])) {
-        self.cssNode->style.dimensions[CSS_WIDTH] = ((WXScrollerComponent 
*)(self.supercomponent)).scrollerCSSNode->style.dimensions[CSS_WIDTH];
-    }
-    
-    if ([self needsLayout]) {
-        layoutNode(self.cssNode, CSS_UNDEFINED, CSS_UNDEFINED, 
CSS_DIRECTION_INHERIT);
-        if ([WXLog logLevel] >= WXLogLevelDebug) {
-            print_css_node(self.cssNode, CSS_PRINT_LAYOUT | CSS_PRINT_STYLE | 
CSS_PRINT_CHILDREN);
-        }
-    }
-    
-    NSMutableSet<WXComponent *> *dirtyComponents = [NSMutableSet set];
-    [self _calculateFrameWithSuperAbsolutePosition:CGPointZero 
gatherDirtyComponents:dirtyComponents];
-    for (WXComponent *dirtyComponent in dirtyComponents) {
-        [self.weexInstance.componentManager _addUITask:^{
-            [dirtyComponent _layoutDidFinish];
-        }];
-    }
-}
-
-@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b77b4259/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.mm
----------------------------------------------------------------------
diff --git 
a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.mm 
b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.mm
new file mode 100644
index 0000000..b1b757a
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.mm
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import "WXCellSlotComponent.h"
+#import "WXComponent_internal.h"
+#import "WXComponentManager.h"
+#import "WXSDKInstance_private.h"
+#import "WXConvert.h"
+#import "WXAssert.h"
+#import "WXScrollerComponent+Layout.h"
+
+@implementation WXCellSlotComponent
+
+- (instancetype)initWithRef:(NSString *)ref
+                       type:(NSString *)type
+                     styles:(NSDictionary *)styles
+                 attributes:(NSDictionary *)attributes
+                     events:(NSArray *)events
+               weexInstance:(WXSDKInstance *)weexInstance
+{
+    self = [super initWithRef:ref type:type styles:styles 
attributes:attributes events:events weexInstance:weexInstance];
+    if (self) {
+        // TODO: isRecycle / insertAnimation / deleteAnimation / 
keepScrollPosition
+        if (attributes[@"default"]) {
+            _templateCaseType = @"default";
+        }
+        _templateCaseType = attributes[@"case"] ? [WXConvert 
NSString:attributes[@"case"]] :const_cast<NSString 
*>(WXDefaultRecycleTemplateType) ;
+        _lazyCreateView = YES;
+        _isNeedJoinLayoutSystem = NO;
+    }
+    
+    return self;
+}
+
+- (void)updateAttributes:(NSDictionary *)attributes
+{
+    
+}
+
+- (void)updateCellData:(NSDictionary *)data
+{
+    WXAssertComponentThread();    
+    
+    [self updateBindingData:data];
+    [self triggerLayout];
+}
+
+- (void)_didInserted
+{
+    [self triggerLayout];
+}
+
+- (void)triggerLayout
+{
+    WXAssertComponentThread();
+    
+//#ifndef USE_FLEX
+    if(![WXComponent isUseFlex])
+    {
+        //TODO: _isUseContainerWidth?
+        if (isUndefined(self.cssNode->style.dimensions[CSS_WIDTH])) {
+            self.cssNode->style.dimensions[CSS_WIDTH] = ((WXScrollerComponent 
*)(self.supercomponent)).scrollerCSSNode->style.dimensions[CSS_WIDTH];
+        }
+        
+        if ([self needsLayout]) {
+            layoutNode(self.cssNode, CSS_UNDEFINED, CSS_UNDEFINED, 
CSS_DIRECTION_INHERIT);
+            if ([WXLog logLevel] >= WXLogLevelDebug) {
+                print_css_node(self.cssNode, 
(css_print_options_t)(CSS_PRINT_LAYOUT | CSS_PRINT_STYLE | CSS_PRINT_CHILDREN));
+            }
+        }
+    }
+
+//#else
+    else
+    {
+        if (flexIsUndefined(self.flexCssNode->getStyleWidth())) {
+            self.flexCssNode->setStyleWidth(((WXScrollerComponent 
*)(self.supercomponent)).flexScrollerCSSNode->getStyleWidth(),NO);
+        }
+        
+        if ([self needsLayout]) {
+            std::pair<float, float> renderPageSize;
+            renderPageSize.first = self.weexInstance.frame.size.width;
+            renderPageSize.second = self.weexInstance.frame.size.height;
+            self.flexCssNode->calculateLayout(renderPageSize);
+            if ([WXLog logLevel] >= WXLogLevelDebug) {
+                
+            }
+        }
+    }
+//#endif
+    
+    NSMutableSet<WXComponent *> *dirtyComponents = [NSMutableSet set];
+    [self _calculateFrameWithSuperAbsolutePosition:CGPointZero 
gatherDirtyComponents:dirtyComponents];
+    for (WXComponent *dirtyComponent in dirtyComponents) {
+        [self.weexInstance.componentManager _addUITask:^{
+            [dirtyComponent _layoutDidFinish];
+        }];
+    }
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b77b4259/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
deleted file mode 100644
index 8f71797..0000000
--- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.m
+++ /dev/null
@@ -1,618 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#import "WXLog.h"
-#import "WXUtility.h"
-#import "WXComponent_internal.h"
-#import "WXComponentManager.h"
-#import "WXSDKInstance_private.h"
-
-#import "WXCellSlotComponent.h"
-#import "WXRecycleListLayout.h"
-#import "WXRecycleListComponent.h"
-#import "WXRecycleListDataManager.h"
-#import "WXRecycleListTemplateManager.h"
-#import "WXRecycleListUpdateManager.h"
-#import "WXBridgeManager.h"
-#import "WXSDKManager.h"
-#import "WXComponent+DataBinding.h"
-
-@interface WXRecycleListComponentView:UICollectionView
-@end
-
-@implementation WXRecycleListComponentView
-- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
shouldReceiveTouch:(UITouch *)touch
-{
-    if ([(id <WXScrollerProtocol>) self.wx_component 
respondsToSelector:@selector(requestGestureShouldStopPropagation:shouldReceiveTouch:)])
 {
-        return [(id <WXScrollerProtocol>) self.wx_component 
requestGestureShouldStopPropagation:gestureRecognizer shouldReceiveTouch:touch];
-    }
-    else{
-        return YES;
-    }
-}
-
-@end
-
-@interface WXRecycleListComponent () <WXRecycleListLayoutDelegate, 
WXRecycleListUpdateDelegate, UICollectionViewDelegateFlowLayout, 
UICollectionViewDataSource>
-
-@end
-
-@implementation WXRecycleListComponent
-{
-    NSString *_templateSwitchKey;
-    NSString *_aliasKey;
-    NSString *_indexKey;
-    __weak UICollectionView *_collectionView;
-    
-    NSMutableDictionary *_sizeCache;
-    NSMutableDictionary *_stickyCache;
-    
-    NSUInteger _previousLoadMoreCellNumber;
-}
-
-WX_EXPORT_METHOD(@selector(appendData:))
-WX_EXPORT_METHOD(@selector(appendRange:))
-WX_EXPORT_METHOD(@selector(insertData:data:))
-WX_EXPORT_METHOD(@selector(updateData:data:))
-WX_EXPORT_METHOD(@selector(removeData:count:))
-WX_EXPORT_METHOD(@selector(moveData:toIndex:))
-WX_EXPORT_METHOD(@selector(scrollTo:options:))
-WX_EXPORT_METHOD(@selector(insertRange:range:))
-WX_EXPORT_METHOD(@selector(setListData:))
-
-- (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]) {
-        _dataManager = attributes[@"listData"]? [[WXRecycleListDataManager 
alloc] initWithData:attributes[@"listData"]] : [WXRecycleListDataManager new];
-        _templateManager = [WXRecycleListTemplateManager new];
-        _updateManager = [WXRecycleListUpdateManager new];
-        _updateManager.delegate = self;
-        _templateSwitchKey = [WXConvert NSString:attributes[@"switch"]];
-        _aliasKey = [WXConvert NSString:attributes[@"alias"]];
-        _indexKey = [WXConvert NSString:attributes[@"index"]];
-        _sizeCache = [NSMutableDictionary dictionary];
-        _stickyCache = [NSMutableDictionary dictionary];
-    }
-    
-    return self;
-}
-
-#pragma mark - WXComponent Methods
-
-- (UIView *)loadView
-{
-    WXRecycleListLayout *layout = [self recycleListLayout];
-    return [[WXRecycleListComponentView alloc] initWithFrame:CGRectZero 
collectionViewLayout:layout];
-}
-
-- (void)viewDidLoad
-{
-    [super viewDidLoad];
-    
-    _collectionView = (UICollectionView *)self.view;
-    _collectionView.allowsSelection = NO;
-    _collectionView.allowsMultipleSelection = NO;
-    _collectionView.dataSource = self;
-    _collectionView.delegate = self;
-    
-    _templateManager.collectionView = _collectionView;
-    _updateManager.collectionView = _collectionView;
-}
-
-- (void)viewWillUnload
-{
-    [super viewWillUnload];
-    
-    _collectionView.dataSource = nil;
-    _collectionView.delegate = nil;
-}
-
-- (void)updateAttributes:(NSDictionary *)attributes
-{
-    [super updateAttributes:attributes];
-    
-    if (attributes[@"listData"]) {
-        NSArray *listData = attributes[@"listData"];
-        [self _updateListData:listData withCompletion:nil animation:NO];
-    }
-    if (attributes[@"switch"]) {
-        _templateSwitchKey = [WXConvert NSString:attributes[@"switch"]];
-    }
-    if (attributes[@"alias"]) {
-        _aliasKey = [WXConvert NSString:attributes[@"alias"]];
-    }
-    if (attributes[@"index"]) {
-        _indexKey = [WXConvert NSString:attributes[@"index"]];
-    }
-    if (attributes[@"scrollDirection"]) {
-        WXScrollDirection newScrollDirection = attributes[@"scrollDirection"] 
? [WXConvert WXScrollDirection:attributes[@"scrollDirection"]] : 
WXScrollDirectionVertical;
-        [self _updateScrollDirection:newScrollDirection];
-    }
-}
-
-- (CGPoint)absolutePositionForComponent:(WXComponent *)component
-{
-    CGPoint position = CGPointZero;
-    UIView *view = component->_view;
-    while (view) {
-        if ([view isKindOfClass:[UICollectionViewCell class]]) {
-            NSIndexPath *indexPath = [_collectionView 
indexPathForCell:(UICollectionViewCell *)view];
-            if (!indexPath) {
-                return CGPointMake(NAN, NAN);
-            }
-            UICollectionViewLayoutAttributes *attributes = [_collectionView 
layoutAttributesForItemAtIndexPath:indexPath];
-            CGPoint cellOrigin = attributes.frame.origin;
-            position = CGPointMake(position.x + cellOrigin.x,
-                                   position.y + cellOrigin.y);
-            break;
-        }
-        position = CGPointMake(position.x + view.frame.origin.x,
-                               position.y + view.frame.origin.y);
-        view = view.superview;
-    }
-    
-    return position;
-}
-
-- (void)setContentSize:(CGSize)contentSize
-{
-    // Do Nothing
-}
-
-- (void)adjustSticky
-{
-    // Do Nothing, sticky is adjusted by layout
-}
-
-#pragma mark - Load More Event
-
-- (void)loadMore
-{
-    [super loadMore];
-    
-    _previousLoadMoreCellNumber = [_collectionView numberOfItemsInSection:0];
-}
-
-- (BOOL)isNeedLoadMore
-{
-    BOOL superNeedLoadMore = [super isNeedLoadMore];
-    return superNeedLoadMore && _previousLoadMoreCellNumber != 
[_collectionView numberOfItemsInSection:0];
-}
-
-- (void)resetLoadmore
-{
-    [super resetLoadmore];
-    _previousLoadMoreCellNumber = 0;
-}
-
-#pragma mark - Exported Component Methods
-
-- (void)appendData:(id)appendingData
-{
-    if (!appendingData){
-        return;
-    }
-    NSMutableArray * newListData = [[_dataManager data] mutableCopy];
-    [newListData addObject:appendingData];
-}
-
-- (void)appendRange:(NSArray*)data
-{
-    if (![data isKindOfClass:[NSArray class]]) {
-        WXLogError(@"wrong format of appending data:%@", data);
-        return;
-    }
-    
-    NSArray *oldData = [_dataManager data];
-    [_updateManager updateWithAppendingData:data oldData:oldData 
completion:nil animation:NO];
-}
-
-- (void)setListData:(NSArray*)data
-{
-    if ([data count]) {
-        [_dataManager updateData:data];
-    }
-}
-- (void)insertData:(NSUInteger)index data:(id)data
-{
-    // TODO: bring the update logic to UpdateManager
-    // TODO: update cell because index has changed
-    NSMutableArray *newListData = [[_dataManager data] mutableCopy];
-    if (index <= newListData.count) {
-        [newListData insertObject:data atIndex:index];
-        [_dataManager updateData:newListData];
-        
-        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index 
inSection:0];
-        
-        [UIView performWithoutAnimation:^{
-            [self->_collectionView insertItemsAtIndexPaths:@[indexPath]];
-        }];
-    }
-}
-
-- (void)updateComponentData:(NSString*)componentDataId 
componentData:(NSDictionary*)componentData callback:(NSString*)callbackId
-{
-    NSMutableDictionary * virtualComponentData = [[_dataManager 
virtualComponentDataWithId:componentDataId] mutableCopy];
-    NSIndexPath * indexPath = virtualComponentData[@"indexPath"];
-    if (!indexPath) {
-        return;
-    }
-    virtualComponentData = virtualComponentData?:[NSMutableDictionary new];
-    [virtualComponentData addEntriesFromDictionary:componentData];
-    [_dataManager updateVirtualComponentData:componentDataId 
data:[virtualComponentData copy]];
-    virtualComponentData[@"@phase"] = @"update";
-    virtualComponentData[@"callbackId"] = callbackId;
-    [self _updateDataForCellSlotAtIndexPath:indexPath 
data:virtualComponentData];
-}
-
-- (void)_updateDataForCellSlotAtIndexPath:(NSIndexPath*)indexPath 
data:(NSDictionary*)data
-{
-    if(!indexPath || !data) {
-        return;
-    }
-    WXPerformBlockOnMainThread(^{
-        UICollectionViewCell * cellView = [self->_collectionView 
cellForItemAtIndexPath:indexPath];
-        WXCellSlotComponent * cellSlotComponent = 
(WXCellSlotComponent*)cellView.wx_component;
-        if (cellSlotComponent) {
-            [self _updateBindingData:data forCell:cellSlotComponent 
atIndexPath:indexPath];
-        }
-        // callback when update virtual component data success.
-        NSString * callbackId = data[@"callbackId"];
-        if (callbackId) {
-            [[WXSDKManager bridgeMgr] callBack:self.weexInstance.instanceId 
funcId:callbackId params:@{@"result":@"success"}];
-        }
-    });
-}
-
-- (void)updateData:(NSUInteger)index data:(id)data
-{
-    NSMutableArray * newListData = [[_dataManager data] mutableCopy];
-    if (!data && index > [newListData count]) {
-        return;
-    }
-    NSIndexPath * indexPath = [NSIndexPath indexPathForRow:index inSection:0];
-    NSDictionary * virtualComponentData = [_dataManager 
virtualComponentDataWithIndexPath:indexPath];
-    if ([virtualComponentData[WXBindingOnceIdentify] boolValue]) {
-        return;
-    }
-    
-    // TODO: bring the update logic to UpdateManager
-    newListData[index] = data;
-    [_dataManager updateData:newListData];
-    NSString* virtualComponentId = [_dataManager 
virtualComponentIdWithIndexPath:indexPath];
-    [_dataManager updateVirtualComponentData:virtualComponentId data:data];
-    NSMutableDictionary * newData = nil;
-    if (![data isKindOfClass:[NSDictionary class]]) {
-         newData = [NSMutableDictionary new];
-        [newData setObject:@"data" forKey:data];
-        data = newData;
-    }
-    newData = [data mutableCopy];
-    newData[@"@phase"] = @"update";
-    [self _updateDataForCellSlotAtIndexPath:indexPath data:[newData copy]];
-}
-
-- (void)insertRange:(NSInteger)index range:(NSArray*)data
-{
-    if (![data count]) {
-        WXLogDebug(@"ignore invalid insertRange");
-        return;
-    }
-    
-    NSMutableArray * newListData = [[_dataManager data] mutableCopy];
-    NSRange range = NSMakeRange(index,[data count]);
-    NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:range];
-    [newListData insertObjects:data atIndexes:indexSet];
-    [_dataManager updateData:newListData];
-    [_collectionView reloadData];
-}
-
-- (void)removeData:(NSInteger)index count:(NSInteger)count
-{
-    // TODO: bring the update logic to UpdateManager
-    
-    NSMutableArray *newListData = [[_dataManager data] mutableCopy];
-    if (index > [newListData count] || index + count - 1 > [newListData 
count]) {
-        
-        return;
-    }
-    NSIndexSet *indexSet = [NSIndexSet 
indexSetWithIndexesInRange:NSMakeRange(index, count)];
-    [newListData removeObjectsAtIndexes:indexSet];
-    __block NSMutableArray<NSIndexPath*>* indexPaths = [NSMutableArray new];
-    [indexSet enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull 
stop) {
-        NSIndexPath* indexPath = [NSIndexPath indexPathForRow:idx inSection:0];
-        [indexPaths addObject:indexPath];
-    }];
-    
-    [_dataManager updateData:newListData];
-    [_dataManager deleteVirtualComponentAtIndexPaths:indexPaths];
-    [UIView performWithoutAnimation:^{
-        [self->_collectionView deleteItemsAtIndexPaths:indexPaths];
-        [self->_collectionView reloadSections:[NSIndexSet 
indexSetWithIndex:0]];
-    }];
-}
-
-- (void)moveData:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex
-{
-    // TODO: bring the update logic to UpdateManager
-    NSMutableArray *newListData = [[_dataManager data] mutableCopy];
-    id data = newListData[fromIndex];
-    [newListData removeObjectAtIndex:fromIndex];
-    [newListData insertObject:data atIndex:toIndex];
-    [_dataManager updateData:newListData];
-    
-    NSIndexPath *fromIndexPath = [NSIndexPath indexPathForItem:fromIndex 
inSection:0];
-    NSIndexPath *toIndexPath = [NSIndexPath indexPathForItem:toIndex 
inSection:0];
-    [UIView performWithoutAnimation:^{
-        [self->_collectionView moveItemAtIndexPath:fromIndexPath 
toIndexPath:toIndexPath];
-    }];
-}
-
-- (void)scrollTo:(NSUInteger)index options:(NSDictionary *)options
-{
-    NSIndexPath *toIndexPath = [NSIndexPath indexPathForItem:index 
inSection:0];
-    BOOL animated = options[@"animated"] ? [WXConvert 
BOOL:options[@"animated"]] : NO;
-    [_collectionView scrollToItemAtIndexPath:toIndexPath 
atScrollPosition:UICollectionViewScrollPositionTop animated:animated];
-}
-
-#pragma mark - WXComponent Internal Methods
-
-- (void)_insertSubcomponent:(WXComponent *)subcomponent 
atIndex:(NSInteger)index
-{
-   [super _insertSubcomponent:subcomponent atIndex:index];
-    
-    if ([subcomponent isKindOfClass:[WXCellSlotComponent class]]) {
-        WXCellSlotComponent *cell = (WXCellSlotComponent*)subcomponent;
-        [self.weexInstance.componentManager _addUITask:^{
-            [_templateManager addTemplate:cell];
-        }];
-        
-        //TODO: update collection view if adding template
-    }
-}
-
-#pragma mark - Private
-
-- (void)_updateBindingData:(id)data forCell:(WXCellSlotComponent 
*)cellComponent atIndexPath:(NSIndexPath *)indexPath
-{
-    id originalData = data;
-    if (![originalData isKindOfClass:[NSDictionary class]]) {
-        if (_aliasKey) {
-            NSMutableDictionary * dictionary = [NSMutableDictionary 
dictionary];
-            [dictionary setObject:data forKey:_aliasKey];
-            data = dictionary;
-        } else {
-            return;
-        }
-    }
-    
-    if (!data[@"indexPath"] || !data[@"recycleListComponentRef"]) {
-        NSMutableDictionary * dataNew = [data mutableCopy];
-        dataNew[@"recycleListComponentRef"] = self.ref;
-        dataNew[@"indexPath"] = indexPath;
-        data = dataNew;
-    }
-    
-    if ([originalData isKindOfClass:[NSDictionary class]] && _aliasKey 
&&!data[@"phase"]) {
-        data = @{_aliasKey:data,@"aliasKey":_aliasKey};
-    }
-    
-    if (_indexKey) {
-        NSMutableDictionary *dataNew = [data mutableCopy];
-        dataNew[_indexKey] = @(indexPath.item);
-        data = dataNew;
-    }
-    
-#ifdef DEBUG
-    NSDate *startTime = [NSDate date];
-#endif
-    
-    WXPerformBlockSyncOnComponentThread(^{
-        [cellComponent updateCellData:[data copy]];
-    });
-#ifdef DEBUG
-    double duration = -[startTime timeIntervalSinceNow] * 1000;
-    WXLogDebug(@"cell:%li update data time:%f", (long)indexPath.item, 
duration);
-#endif
-    
-    NSValue *cachedSize = _sizeCache[indexPath];
-    if (!cachedSize || !CGSizeEqualToSize([cachedSize CGSizeValue] , 
cellComponent.calculatedFrame.size)) {
-        _sizeCache[indexPath] = [NSValue 
valueWithCGSize:cellComponent.calculatedFrame.size];
-        [_collectionView.collectionViewLayout invalidateLayout];
-    }
-    NSNumber *cachedSticky = _stickyCache[indexPath];
-    BOOL isSticky = cellComponent->_positionType == WXPositionTypeSticky;
-    if (!cachedSticky || [cachedSticky boolValue] != isSticky) {
-        _stickyCache[indexPath] = @(isSticky);
-    }
-}
-
-- (void)_updateListData:(NSArray *)newData
-        withCompletion:(WXRecycleListUpdateCompletion)completion
-             animation:(BOOL)animation
-{
-    if (![newData isKindOfClass:[NSArray class]]) {
-        WXLogError(@"wrong format of list data:%@", newData);
-        completion(NO);
-        return;
-    }
-    
-    NSArray *oldData = [_dataManager data];
-    [_updateManager updateWithNewData:newData oldData:oldData 
completion:completion animation:animation];
-}
-
-- (void)_updateScrollDirection:(WXScrollDirection)newScrollDirection
-{   
-    WXRecycleListLayout *layout = [self recycleListLayout];
-    _collectionView.collectionViewLayout = layout;
-}
-
-- (WXRecycleListLayout *)recycleListLayout
-{
-    WXRecycleListLayout *layout = [WXRecycleListLayout new];
-    layout.delegate = self;
-    // to show cells that original width / height is zero, otherwise 
cellForItemAtIndexPath will not be called
-    layout.minimumLineSpacing = 0.01;
-    layout.minimumInteritemSpacing = 0.01;
-    if (WXScrollDirectionHorizontal == self.scrollDirection) {
-        layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
-    }
-    return layout;
-}
-
-#pragma mark - UICollectionViewDataSource
-
-- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView 
*)collectionView
-{
-    return 1;
-}
-
-- (NSInteger)collectionView:(UICollectionView *)collectionView 
numberOfItemsInSection:(NSInteger)section
-{
-    return [_dataManager numberOfItems];
-}
-
-- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView 
cellForItemAtIndexPath:(NSIndexPath *)indexPath
-{
-    // 1. get the data relating to the cell
-    id data = [_dataManager dataAtIndex:indexPath.row];
-    
-    // 2. get the template type specified by data
-    NSString * templateType = [self templateType:indexPath];
-    _templateManager.collectionView = collectionView;
-    if (!templateType) {
-        WXLogError(@"Each data should have a value for %@ to indicate template 
type", _templateSwitchKey);
-        return nil;
-    }
-    
-    // 3. dequeue a cell component by template type
-    UICollectionViewCell *cellView = [_collectionView 
dequeueReusableCellWithReuseIdentifier:templateType forIndexPath:indexPath];
-    WXCellSlotComponent *cellComponent = (WXCellSlotComponent 
*)cellView.wx_component;
-    if (!cellComponent) {
-        cellComponent = [_templateManager dequeueCellSlotWithType:templateType 
forIndexPath:indexPath];
-        cellView.wx_component = cellComponent;
-        WXPerformBlockOnComponentThread(^{
-            //TODO: How can we avoid this?
-            [super _insertSubcomponent:cellComponent 
atIndex:self.subcomponents.count];
-        });
-    }
-    
-    // 4. binding the data to the cell component
-    [self _updateBindingData:data forCell:cellComponent atIndexPath:indexPath];
-
-    // 5. Add cell component's view to content view.
-    UIView *contentView = cellComponent.view;
-    if (contentView.superview == cellView.contentView) {
-        return cellView;
-    }
-    
-    for (UIView *view in cellView.contentView.subviews) {
-        [view removeFromSuperview];
-    }
-    [cellView.contentView addSubview:contentView];
-    [cellView setAccessibilityIdentifier:contentView.accessibilityIdentifier];
-    
-    WXLogDebug(@"Return cell view:%@, indexPath:%@", cellView, indexPath);
-    
-    [self handleAppear];
-    
-    return cellView;
-}
-
-- (UICollectionReusableView *)collectionView:(UICollectionView 
*)collectionView viewForSupplementaryElementOfKind:(NSString *)kind 
atIndexPath:(NSIndexPath *)indexPath
-{
-    return nil;
-}
-
-#pragma mark - UICollectionViewDelegate
-
-- (void)collectionView:(UICollectionView *)collectionView 
willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath 
*)indexPath
-{
-    WXLogDebug(@"will display cell:%@, at index path:%@", cell, indexPath);
-}
-
-- (void)collectionView:(UICollectionView *)collectionView 
didEndDisplayingCell:(UICollectionViewCell *)cell 
forItemAtIndexPath:(NSIndexPath *)indexPath
-{
-    WXLogDebug(@"Did end displaying cell:%@, at index path:%@", cell, 
indexPath);
-}
-
-#pragma mark - UICollectionViewDelegateFlowLayout
-
-- (CGSize)collectionView:(UICollectionView *)collectionView 
layout:(UICollectionViewLayout *)collectionViewLayout 
sizeForItemAtIndexPath:(NSIndexPath *)indexPath
-{
-    NSValue *size = _sizeCache[indexPath];
-    if (size) {
-        return [size CGSizeValue];
-    } else {
-
-        WXCellSlotComponent *cell = [_templateManager templateWithType:[self 
templateType:indexPath]];
-        CGSize size = cell.calculatedFrame.size;
-        _sizeCache[indexPath] = [NSValue valueWithCGSize:size];
-        return CGSizeMake(_collectionView.frame.size.width, size.height);
-    }
-}
-
-#pragma mark - WXRecycleListLayoutDelegate
-
-- (BOOL)collectionView:(UICollectionView *)collectionView 
layout:(UICollectionViewLayout *)collectionViewLayout 
isNeedStickyForIndexPath:(NSIndexPath *)indexPath
-{
-    NSNumber *cachedSticky = _stickyCache[indexPath];
-    if (cachedSticky) {
-        return [cachedSticky boolValue];
-    } else {
-        return NO;
-    }
-}
-
-#pragma mark - WXRecycleListUpdateDelegate
-
-- (void)updateManager:(WXRecycleListUpdateManager *)manager 
willUpdateData:(id)newData
-{
-    [_dataManager updateData:newData];
-}
-
-- (void)updateManager:(WXRecycleListUpdateManager *)manager 
didUpdateData:(id)newData withSuccess:(BOOL)finished
-{
-    
-}
-
-- (NSString*)templateType:(NSIndexPath*)indexPath
-{
-    NSDictionary *data = [_dataManager dataAtIndex:indexPath.row];
-    // default is first template.
-    NSString *templateType = [_templateManager topTemplate].templateCaseType;
-    if (!data || ![data isKindOfClass:[NSDictionary class]]) {
-        return templateType;
-    }
-    
-    if (_templateSwitchKey &&data[_templateSwitchKey]){
-        templateType = data[_templateSwitchKey];
-    } else if (data[WXDefaultRecycleTemplateType]){
-        // read the default type.
-        templateType = data[WXDefaultRecycleTemplateType];
-    }
-    return templateType;
-}
-
-@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b77b4259/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.mm
----------------------------------------------------------------------
diff --git 
a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.mm 
b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.mm
new file mode 100644
index 0000000..551acd9
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.mm
@@ -0,0 +1,619 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import "WXLog.h"
+#import "WXUtility.h"
+#import "WXComponent_internal.h"
+#import "WXComponentManager.h"
+#import "WXSDKInstance_private.h"
+
+#import "WXCellSlotComponent.h"
+#import "WXRecycleListLayout.h"
+#import "WXRecycleListComponent.h"
+#import "WXRecycleListDataManager.h"
+#import "WXRecycleListTemplateManager.h"
+#import "WXRecycleListUpdateManager.h"
+#import "WXBridgeManager.h"
+#import "WXSDKManager.h"
+#import "WXComponent+DataBinding.h"
+#import "WXComponent+Layout.h"
+
+@interface WXRecycleListComponentView:UICollectionView
+@end
+
+@implementation WXRecycleListComponentView
+- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
shouldReceiveTouch:(UITouch *)touch
+{
+    if ([(id <WXScrollerProtocol>) self.wx_component 
respondsToSelector:@selector(requestGestureShouldStopPropagation:shouldReceiveTouch:)])
 {
+        return [(id <WXScrollerProtocol>) self.wx_component 
requestGestureShouldStopPropagation:gestureRecognizer shouldReceiveTouch:touch];
+    }
+    else{
+        return YES;
+    }
+}
+
+@end
+
+@interface WXRecycleListComponent () <WXRecycleListLayoutDelegate, 
WXRecycleListUpdateDelegate, UICollectionViewDelegateFlowLayout, 
UICollectionViewDataSource>
+
+@end
+
+@implementation WXRecycleListComponent
+{
+    NSString *_templateSwitchKey;
+    NSString *_aliasKey;
+    NSString *_indexKey;
+    __weak UICollectionView *_collectionView;
+    
+    NSMutableDictionary *_sizeCache;
+    NSMutableDictionary *_stickyCache;
+    
+    NSUInteger _previousLoadMoreCellNumber;
+}
+
+WX_EXPORT_METHOD(@selector(appendData:))
+WX_EXPORT_METHOD(@selector(appendRange:))
+WX_EXPORT_METHOD(@selector(insertData:data:))
+WX_EXPORT_METHOD(@selector(updateData:data:))
+WX_EXPORT_METHOD(@selector(removeData:count:))
+WX_EXPORT_METHOD(@selector(moveData:toIndex:))
+WX_EXPORT_METHOD(@selector(scrollTo:options:))
+WX_EXPORT_METHOD(@selector(insertRange:range:))
+WX_EXPORT_METHOD(@selector(setListData:))
+
+- (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]) {
+        _dataManager = attributes[@"listData"]? [[WXRecycleListDataManager 
alloc] initWithData:attributes[@"listData"]] : [WXRecycleListDataManager new];
+        _templateManager = [WXRecycleListTemplateManager new];
+        _updateManager = [WXRecycleListUpdateManager new];
+        _updateManager.delegate = self;
+        _templateSwitchKey = [WXConvert NSString:attributes[@"switch"]];
+        _aliasKey = [WXConvert NSString:attributes[@"alias"]];
+        _indexKey = [WXConvert NSString:attributes[@"index"]];
+        _sizeCache = [NSMutableDictionary dictionary];
+        _stickyCache = [NSMutableDictionary dictionary];
+    }
+    
+    return self;
+}
+
+#pragma mark - WXComponent Methods
+
+- (UIView *)loadView
+{
+    WXRecycleListLayout *layout = [self recycleListLayout];
+    return [[WXRecycleListComponentView alloc] initWithFrame:CGRectZero 
collectionViewLayout:layout];
+}
+
+- (void)viewDidLoad
+{
+    [super viewDidLoad];
+    
+    _collectionView = (UICollectionView *)self.view;
+    _collectionView.allowsSelection = NO;
+    _collectionView.allowsMultipleSelection = NO;
+    _collectionView.dataSource = self;
+    _collectionView.delegate = self;
+    
+    _templateManager.collectionView = _collectionView;
+    _updateManager.collectionView = _collectionView;
+}
+
+- (void)viewWillUnload
+{
+    [super viewWillUnload];
+    
+    _collectionView.dataSource = nil;
+    _collectionView.delegate = nil;
+}
+
+- (void)updateAttributes:(NSDictionary *)attributes
+{
+    [super updateAttributes:attributes];
+    
+    if (attributes[@"listData"]) {
+        NSArray *listData = attributes[@"listData"];
+        [self _updateListData:listData withCompletion:nil animation:NO];
+    }
+    if (attributes[@"switch"]) {
+        _templateSwitchKey = [WXConvert NSString:attributes[@"switch"]];
+    }
+    if (attributes[@"alias"]) {
+        _aliasKey = [WXConvert NSString:attributes[@"alias"]];
+    }
+    if (attributes[@"index"]) {
+        _indexKey = [WXConvert NSString:attributes[@"index"]];
+    }
+    if (attributes[@"scrollDirection"]) {
+        WXScrollDirection newScrollDirection = attributes[@"scrollDirection"] 
? [WXConvert WXScrollDirection:attributes[@"scrollDirection"]] : 
WXScrollDirectionVertical;
+        [self _updateScrollDirection:newScrollDirection];
+    }
+}
+
+- (CGPoint)absolutePositionForComponent:(WXComponent *)component
+{
+    CGPoint position = CGPointZero;
+    UIView *view = component->_view;
+    while (view) {
+        if ([view isKindOfClass:[UICollectionViewCell class]]) {
+            NSIndexPath *indexPath = [_collectionView 
indexPathForCell:(UICollectionViewCell *)view];
+            if (!indexPath) {
+                return CGPointMake(NAN, NAN);
+            }
+            UICollectionViewLayoutAttributes *attributes = [_collectionView 
layoutAttributesForItemAtIndexPath:indexPath];
+            CGPoint cellOrigin = attributes.frame.origin;
+            position = CGPointMake(position.x + cellOrigin.x,
+                                   position.y + cellOrigin.y);
+            break;
+        }
+        position = CGPointMake(position.x + view.frame.origin.x,
+                               position.y + view.frame.origin.y);
+        view = view.superview;
+    }
+    
+    return position;
+}
+
+- (void)setContentSize:(CGSize)contentSize
+{
+    // Do Nothing
+}
+
+- (void)adjustSticky
+{
+    // Do Nothing, sticky is adjusted by layout
+}
+
+#pragma mark - Load More Event
+
+- (void)loadMore
+{
+    [super loadMore];
+    
+    _previousLoadMoreCellNumber = [_collectionView numberOfItemsInSection:0];
+}
+
+- (BOOL)isNeedLoadMore
+{
+    BOOL superNeedLoadMore = [super isNeedLoadMore];
+    return superNeedLoadMore && _previousLoadMoreCellNumber != 
[_collectionView numberOfItemsInSection:0];
+}
+
+- (void)resetLoadmore
+{
+    [super resetLoadmore];
+    _previousLoadMoreCellNumber = 0;
+}
+
+#pragma mark - Exported Component Methods
+
+- (void)appendData:(id)appendingData
+{
+    if (!appendingData){
+        return;
+    }
+    NSMutableArray * newListData = [[_dataManager data] mutableCopy];
+    [newListData addObject:appendingData];
+}
+
+- (void)appendRange:(NSArray*)data
+{
+    if (![data isKindOfClass:[NSArray class]]) {
+        WXLogError(@"wrong format of appending data:%@", data);
+        return;
+    }
+    
+    NSArray *oldData = [_dataManager data];
+    [_updateManager updateWithAppendingData:data oldData:oldData 
completion:nil animation:NO];
+}
+
+- (void)setListData:(NSArray*)data
+{
+    if ([data count]) {
+        [_dataManager updateData:data];
+    }
+}
+- (void)insertData:(NSUInteger)index data:(id)data
+{
+    // TODO: bring the update logic to UpdateManager
+    // TODO: update cell because index has changed
+    NSMutableArray *newListData = [[_dataManager data] mutableCopy];
+    if (index <= newListData.count) {
+        [newListData insertObject:data atIndex:index];
+        [_dataManager updateData:newListData];
+        
+        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index 
inSection:0];
+        
+        [UIView performWithoutAnimation:^{
+            [self->_collectionView insertItemsAtIndexPaths:@[indexPath]];
+        }];
+    }
+}
+
+- (void)updateComponentData:(NSString*)componentDataId 
componentData:(NSDictionary*)componentData callback:(NSString*)callbackId
+{
+    NSMutableDictionary * virtualComponentData = [[_dataManager 
virtualComponentDataWithId:componentDataId] mutableCopy];
+    NSIndexPath * indexPath = virtualComponentData[@"indexPath"];
+    if (!indexPath) {
+        return;
+    }
+    virtualComponentData = virtualComponentData?:[NSMutableDictionary new];
+    [virtualComponentData addEntriesFromDictionary:componentData];
+    [_dataManager updateVirtualComponentData:componentDataId 
data:[virtualComponentData copy]];
+    virtualComponentData[@"@phase"] = @"update";
+    virtualComponentData[@"callbackId"] = callbackId;
+    [self _updateDataForCellSlotAtIndexPath:indexPath 
data:virtualComponentData];
+}
+
+- (void)_updateDataForCellSlotAtIndexPath:(NSIndexPath*)indexPath 
data:(NSDictionary*)data
+{
+    if(!indexPath || !data) {
+        return;
+    }
+    WXPerformBlockOnMainThread(^{
+        UICollectionViewCell * cellView = [self->_collectionView 
cellForItemAtIndexPath:indexPath];
+        WXCellSlotComponent * cellSlotComponent = 
(WXCellSlotComponent*)cellView.wx_component;
+        if (cellSlotComponent) {
+            [self _updateBindingData:data forCell:cellSlotComponent 
atIndexPath:indexPath];
+        }
+        // callback when update virtual component data success.
+        NSString * callbackId = data[@"callbackId"];
+        if (callbackId) {
+            [[WXSDKManager bridgeMgr] callBack:self.weexInstance.instanceId 
funcId:callbackId params:@{@"result":@"success"}];
+        }
+    });
+}
+
+- (void)updateData:(NSUInteger)index data:(id)data
+{
+    NSMutableArray * newListData = [[_dataManager data] mutableCopy];
+    if (!data && index > [newListData count]) {
+        return;
+    }
+    NSIndexPath * indexPath = [NSIndexPath indexPathForRow:index inSection:0];
+    NSDictionary * virtualComponentData = [_dataManager 
virtualComponentDataWithIndexPath:indexPath];
+    if ([virtualComponentData[WXBindingOnceIdentify] boolValue]) {
+        return;
+    }
+    
+    // TODO: bring the update logic to UpdateManager
+    newListData[index] = data;
+    [_dataManager updateData:newListData];
+    NSString* virtualComponentId = [_dataManager 
virtualComponentIdWithIndexPath:indexPath];
+    [_dataManager updateVirtualComponentData:virtualComponentId data:data];
+    NSMutableDictionary * newData = nil;
+    if (![data isKindOfClass:[NSDictionary class]]) {
+         newData = [NSMutableDictionary new];
+        [newData setObject:@"data" forKey:data];
+        data = newData;
+    }
+    newData = [data mutableCopy];
+    newData[@"@phase"] = @"update";
+    [self _updateDataForCellSlotAtIndexPath:indexPath data:[newData copy]];
+}
+
+- (void)insertRange:(NSInteger)index range:(NSArray*)data
+{
+    if (![data count]) {
+        WXLogDebug(@"ignore invalid insertRange");
+        return;
+    }
+    
+    NSMutableArray * newListData = [[_dataManager data] mutableCopy];
+    NSRange range = NSMakeRange(index,[data count]);
+    NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:range];
+    [newListData insertObjects:data atIndexes:indexSet];
+    [_dataManager updateData:newListData];
+    [_collectionView reloadData];
+}
+
+- (void)removeData:(NSInteger)index count:(NSInteger)count
+{
+    // TODO: bring the update logic to UpdateManager
+    
+    NSMutableArray *newListData = [[_dataManager data] mutableCopy];
+    if (index > [newListData count] || index + count - 1 > [newListData 
count]) {
+        
+        return;
+    }
+    NSIndexSet *indexSet = [NSIndexSet 
indexSetWithIndexesInRange:NSMakeRange(index, count)];
+    [newListData removeObjectsAtIndexes:indexSet];
+    __block NSMutableArray<NSIndexPath*>* indexPaths = [NSMutableArray new];
+    [indexSet enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull 
stop) {
+        NSIndexPath* indexPath = [NSIndexPath indexPathForRow:idx inSection:0];
+        [indexPaths addObject:indexPath];
+    }];
+    
+    [_dataManager updateData:newListData];
+    [_dataManager deleteVirtualComponentAtIndexPaths:indexPaths];
+    [UIView performWithoutAnimation:^{
+        [self->_collectionView deleteItemsAtIndexPaths:indexPaths];
+        [self->_collectionView reloadSections:[NSIndexSet 
indexSetWithIndex:0]];
+    }];
+}
+
+- (void)moveData:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex
+{
+    // TODO: bring the update logic to UpdateManager
+    NSMutableArray *newListData = [[_dataManager data] mutableCopy];
+    id data = newListData[fromIndex];
+    [newListData removeObjectAtIndex:fromIndex];
+    [newListData insertObject:data atIndex:toIndex];
+    [_dataManager updateData:newListData];
+    
+    NSIndexPath *fromIndexPath = [NSIndexPath indexPathForItem:fromIndex 
inSection:0];
+    NSIndexPath *toIndexPath = [NSIndexPath indexPathForItem:toIndex 
inSection:0];
+    [UIView performWithoutAnimation:^{
+        [self->_collectionView moveItemAtIndexPath:fromIndexPath 
toIndexPath:toIndexPath];
+    }];
+}
+
+- (void)scrollTo:(NSUInteger)index options:(NSDictionary *)options
+{
+    NSIndexPath *toIndexPath = [NSIndexPath indexPathForItem:index 
inSection:0];
+    BOOL animated = options[@"animated"] ? [WXConvert 
BOOL:options[@"animated"]] : NO;
+    [_collectionView scrollToItemAtIndexPath:toIndexPath 
atScrollPosition:UICollectionViewScrollPositionTop animated:animated];
+}
+
+#pragma mark - WXComponent Internal Methods
+
+- (void)_insertSubcomponent:(WXComponent *)subcomponent 
atIndex:(NSInteger)index
+{
+   [super _insertSubcomponent:subcomponent atIndex:index];
+    
+    if ([subcomponent isKindOfClass:[WXCellSlotComponent class]]) {
+        WXCellSlotComponent *cell = (WXCellSlotComponent*)subcomponent;
+        [self.weexInstance.componentManager _addUITask:^{
+            [_templateManager addTemplate:cell];
+        }];
+        
+        //TODO: update collection view if adding template
+    }
+}
+
+#pragma mark - Private
+
+- (void)_updateBindingData:(id)data forCell:(WXCellSlotComponent 
*)cellComponent atIndexPath:(NSIndexPath *)indexPath
+{
+    id originalData = data;
+    if (![originalData isKindOfClass:[NSDictionary class]]) {
+        if (_aliasKey) {
+            NSMutableDictionary * dictionary = [NSMutableDictionary 
dictionary];
+            [dictionary setObject:data forKey:_aliasKey];
+            data = dictionary;
+        } else {
+            return;
+        }
+    }
+    
+    if (!data[@"indexPath"] || !data[@"recycleListComponentRef"]) {
+        NSMutableDictionary * dataNew = [data mutableCopy];
+        dataNew[@"recycleListComponentRef"] = self.ref;
+        dataNew[@"indexPath"] = indexPath;
+        data = dataNew;
+    }
+    
+    if ([originalData isKindOfClass:[NSDictionary class]] && _aliasKey 
&&!data[@"phase"]) {
+        data = @{_aliasKey:data,@"aliasKey":_aliasKey};
+    }
+    
+    if (_indexKey) {
+        NSMutableDictionary *dataNew = [data mutableCopy];
+        dataNew[_indexKey] = @(indexPath.item);
+        data = dataNew;
+    }
+    
+#ifdef DEBUG
+    NSDate *startTime = [NSDate date];
+#endif
+    
+    WXPerformBlockSyncOnComponentThread(^{
+        [cellComponent updateCellData:[data copy]];
+    });
+#ifdef DEBUG
+    double duration = -[startTime timeIntervalSinceNow] * 1000;
+    WXLogDebug(@"cell:%li update data time:%f", (long)indexPath.item, 
duration);
+#endif
+    
+    NSValue *cachedSize = _sizeCache[indexPath];
+    if (!cachedSize || !CGSizeEqualToSize([cachedSize CGSizeValue] , 
cellComponent.calculatedFrame.size)) {
+        _sizeCache[indexPath] = [NSValue 
valueWithCGSize:cellComponent.calculatedFrame.size];
+        [_collectionView.collectionViewLayout invalidateLayout];
+    }
+    NSNumber *cachedSticky = _stickyCache[indexPath];
+    BOOL isSticky = cellComponent->_positionType == WXPositionTypeSticky;
+    if (!cachedSticky || [cachedSticky boolValue] != isSticky) {
+        _stickyCache[indexPath] = @(isSticky);
+    }
+}
+
+- (void)_updateListData:(NSArray *)newData
+        withCompletion:(WXRecycleListUpdateCompletion)completion
+             animation:(BOOL)animation
+{
+    if (![newData isKindOfClass:[NSArray class]]) {
+        WXLogError(@"wrong format of list data:%@", newData);
+        completion(NO);
+        return;
+    }
+    
+    NSArray *oldData = [_dataManager data];
+    [_updateManager updateWithNewData:newData oldData:oldData 
completion:completion animation:animation];
+}
+
+- (void)_updateScrollDirection:(WXScrollDirection)newScrollDirection
+{   
+    WXRecycleListLayout *layout = [self recycleListLayout];
+    _collectionView.collectionViewLayout = layout;
+}
+
+- (WXRecycleListLayout *)recycleListLayout
+{
+    WXRecycleListLayout *layout = [WXRecycleListLayout new];
+    layout.delegate = self;
+    // to show cells that original width / height is zero, otherwise 
cellForItemAtIndexPath will not be called
+    layout.minimumLineSpacing = 0.01;
+    layout.minimumInteritemSpacing = 0.01;
+    if (WXScrollDirectionHorizontal == self.scrollDirection) {
+        layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
+    }
+    return layout;
+}
+
+#pragma mark - UICollectionViewDataSource
+
+- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView 
*)collectionView
+{
+    return 1;
+}
+
+- (NSInteger)collectionView:(UICollectionView *)collectionView 
numberOfItemsInSection:(NSInteger)section
+{
+    return [_dataManager numberOfItems];
+}
+
+- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView 
cellForItemAtIndexPath:(NSIndexPath *)indexPath
+{
+    // 1. get the data relating to the cell
+    id data = [_dataManager dataAtIndex:indexPath.row];
+    
+    // 2. get the template type specified by data
+    NSString * templateType = [self templateType:indexPath];
+    _templateManager.collectionView = collectionView;
+    if (!templateType) {
+        WXLogError(@"Each data should have a value for %@ to indicate template 
type", _templateSwitchKey);
+        return nil;
+    }
+    
+    // 3. dequeue a cell component by template type
+    UICollectionViewCell *cellView = [_collectionView 
dequeueReusableCellWithReuseIdentifier:templateType forIndexPath:indexPath];
+    WXCellSlotComponent *cellComponent = (WXCellSlotComponent 
*)cellView.wx_component;
+    if (!cellComponent) {
+        cellComponent = [_templateManager dequeueCellSlotWithType:templateType 
forIndexPath:indexPath];
+        cellView.wx_component = cellComponent;
+        WXPerformBlockOnComponentThread(^{
+            //TODO: How can we avoid this?
+            [super _insertSubcomponent:cellComponent 
atIndex:self.subcomponents.count];
+        });
+    }
+    
+    // 4. binding the data to the cell component
+    [self _updateBindingData:data forCell:cellComponent atIndexPath:indexPath];
+
+    // 5. Add cell component's view to content view.
+    UIView *contentView = cellComponent.view;
+    if (contentView.superview == cellView.contentView) {
+        return cellView;
+    }
+    
+    for (UIView *view in cellView.contentView.subviews) {
+        [view removeFromSuperview];
+    }
+    [cellView.contentView addSubview:contentView];
+    [cellView setAccessibilityIdentifier:contentView.accessibilityIdentifier];
+    
+    WXLogDebug(@"Return cell view:%@, indexPath:%@", cellView, indexPath);
+    
+    [self handleAppear];
+    
+    return cellView;
+}
+
+- (UICollectionReusableView *)collectionView:(UICollectionView 
*)collectionView viewForSupplementaryElementOfKind:(NSString *)kind 
atIndexPath:(NSIndexPath *)indexPath
+{
+    return nil;
+}
+
+#pragma mark - UICollectionViewDelegate
+
+- (void)collectionView:(UICollectionView *)collectionView 
willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath 
*)indexPath
+{
+    WXLogDebug(@"will display cell:%@, at index path:%@", cell, indexPath);
+}
+
+- (void)collectionView:(UICollectionView *)collectionView 
didEndDisplayingCell:(UICollectionViewCell *)cell 
forItemAtIndexPath:(NSIndexPath *)indexPath
+{
+    WXLogDebug(@"Did end displaying cell:%@, at index path:%@", cell, 
indexPath);
+}
+
+#pragma mark - UICollectionViewDelegateFlowLayout
+
+- (CGSize)collectionView:(UICollectionView *)collectionView 
layout:(UICollectionViewLayout *)collectionViewLayout 
sizeForItemAtIndexPath:(NSIndexPath *)indexPath
+{
+    NSValue *size = _sizeCache[indexPath];
+    if (size) {
+        return [size CGSizeValue];
+    } else {
+
+        WXCellSlotComponent *cell = [_templateManager templateWithType:[self 
templateType:indexPath]];
+        CGSize size = cell.calculatedFrame.size;
+        _sizeCache[indexPath] = [NSValue valueWithCGSize:size];
+        return CGSizeMake(_collectionView.frame.size.width, size.height);
+    }
+}
+
+#pragma mark - WXRecycleListLayoutDelegate
+
+- (BOOL)collectionView:(UICollectionView *)collectionView 
layout:(UICollectionViewLayout *)collectionViewLayout 
isNeedStickyForIndexPath:(NSIndexPath *)indexPath
+{
+    NSNumber *cachedSticky = _stickyCache[indexPath];
+    if (cachedSticky) {
+        return [cachedSticky boolValue];
+    } else {
+        return NO;
+    }
+}
+
+#pragma mark - WXRecycleListUpdateDelegate
+
+- (void)updateManager:(WXRecycleListUpdateManager *)manager 
willUpdateData:(id)newData
+{
+    [_dataManager updateData:newData];
+}
+
+- (void)updateManager:(WXRecycleListUpdateManager *)manager 
didUpdateData:(id)newData withSuccess:(BOOL)finished
+{
+    
+}
+
+- (NSString*)templateType:(NSIndexPath*)indexPath
+{
+    NSDictionary *data = [_dataManager dataAtIndex:indexPath.row];
+    // default is first template.
+    NSString *templateType = [_templateManager topTemplate].templateCaseType;
+    if (!data || ![data isKindOfClass:[NSDictionary class]]) {
+        return templateType;
+    }
+    
+    if (_templateSwitchKey &&data[_templateSwitchKey]){
+        templateType = data[_templateSwitchKey];
+    } else if (data[WXDefaultRecycleTemplateType]){
+        // read the default type.
+        templateType = data[WXDefaultRecycleTemplateType];
+    }
+    return templateType;
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b77b4259/ios/sdk/WeexSDK/Sources/Component/Recycler/WXRecyclerComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/Recycler/WXRecyclerComponent.m 
b/ios/sdk/WeexSDK/Sources/Component/Recycler/WXRecyclerComponent.m
deleted file mode 100644
index 7ca1de6..0000000
--- a/ios/sdk/WeexSDK/Sources/Component/Recycler/WXRecyclerComponent.m
+++ /dev/null
@@ -1,738 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#import "WXRecyclerComponent.h"
-#import "WXComponent_internal.h"
-#import "WXSDKInstance_private.h"
-#import "WXRecyclerDataController.h"
-#import "WXRecyclerUpdateController.h"
-#import "WXMultiColumnLayout.h"
-#import "WXHeaderComponent.h"
-#import "WXFooterComponent.h"
-#import "WXCellComponent.h"
-#import "WXAssert.h"
-#import "WXConvert.h"
-#import "WXUtility.h"
-#import "WXMonitor.h"
-#import "NSObject+WXSwizzle.h"
-#import "WXComponent+Events.h"
-#import "WXRecyclerDragController.h"
-
-static NSString * const kCollectionCellReuseIdentifier = @"WXRecyclerCell";
-static NSString * const kCollectionHeaderReuseIdentifier = @"WXRecyclerHeader";
-static float const kRecyclerNormalColumnGap = 32;
-
-typedef enum : NSUInteger {
-    WXRecyclerLayoutTypeMultiColumn,
-    WXRecyclerLayoutTypeFlex,
-    WXRecyclerLayoutTypeGrid,
-} WXRecyclerLayoutType;
-
-@interface WXCollectionView : UICollectionView
-
-@end
-
-@implementation WXCollectionView
-
-- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index
-{
-    [super insertSubview:view atIndex:index];
-}
-
-- (void)layoutSubviews
-{
-    [super layoutSubviews];
-    [self.wx_component layoutDidFinish];
-}
-
-- (void)setContentOffset:(CGPoint)contentOffset
-{
-    // FIXME: side effect caused by hooking _adjustContentOffsetIfNecessary.
-    // When UICollectionView is pulled down and finger 
releases,contentOffset 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;
-    }
-    if (isnan(contentOffset.x)) {
-        contentOffset.x = 0;
-    }
-    if(isnan(contentOffset.y)) {
-        contentOffset.y = 0;
-    }
-    
-    [super setContentOffset:contentOffset];
-}
-
-@end
-
-@interface WXCollectionViewCell : UICollectionViewCell
-
-@end
-
-@implementation WXCollectionViewCell
-
-- (void)prepareForReuse
-{
-    [super prepareForReuse];
-    
-    WXCellComponent *cellComponent = (WXCellComponent *)self.wx_component;
-    if (cellComponent.isRecycle && [cellComponent isViewLoaded] && 
[self.contentView.subviews containsObject:cellComponent.view]) {
-        [cellComponent _unloadViewWithReusing:YES];
-    }
-}
-
-@end
-
-@interface WXRecyclerComponent () <UICollectionViewDataSource, 
UICollectionViewDelegate, WXMultiColumnLayoutDelegate, 
WXRecyclerUpdateControllerDelegate, WXCellRenderDelegate, 
WXHeaderRenderDelegate, WXRecyclerDragControllerDelegate>
-
-@property (nonatomic, strong, readonly) WXRecyclerDataController 
*dataController;
-@property (nonatomic, strong, readonly) WXRecyclerUpdateController 
*updateController;
-@property (nonatomic, weak, readonly) UICollectionView *collectionView;
-@property (nonatomic, strong) WXRecyclerDragController *dragController;
-
-@end
-
-@implementation WXRecyclerComponent
-{
-    WXRecyclerLayoutType _layoutType;
-    UICollectionViewLayout *_collectionViewlayout;
-    
-    UIEdgeInsets _padding;
-    NSUInteger _previousLoadMoreCellNumber;
-}
-
-- (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]) {
-        [self _fillPadding];
-        
-        if ([type isEqualToString:@"waterfall"] || (attributes[@"layout"] && 
[attributes[@"layout"] isEqualToString:@"multi-column"])) {
-            // TODO: abstraction
-            _layoutType = WXRecyclerLayoutTypeMultiColumn;
-            CGFloat scaleFactor = weexInstance.pixelScaleFactor;
-            _collectionViewlayout = [WXMultiColumnLayout new];
-            WXMultiColumnLayout *layout = (WXMultiColumnLayout 
*)_collectionViewlayout;
-            layout.columnWidth = [WXConvert 
WXLength:attributes[@"columnWidth"] isFloat:YES scaleFactor:scaleFactor] ? : 
[WXLength lengthWithFloat:0.0 type:WXLengthTypeAuto];
-            layout.columnCount = [WXConvert 
WXLength:attributes[@"columnCount"] isFloat:NO scaleFactor:1.0] ? : [WXLength 
lengthWithInt:1 type:WXLengthTypeFixed];
-            if (attributes[@"leftGap"]) {
-                layout.leftGap = [WXConvert WXPixelType:attributes[@"leftGap"] 
scaleFactor:scaleFactor];
-            }
-            if (attributes[@"rightGap"]) {
-                layout.rightGap = [WXConvert 
WXPixelType:attributes[@"rightGap"] scaleFactor:scaleFactor];
-            }
-            layout.columnGap = [self _floatValueForColumnGap:([WXConvert 
WXLength:attributes[@"columnGap"] isFloat:YES scaleFactor:scaleFactor] ? : 
[WXLength lengthWithFloat:0.0 type:WXLengthTypeNormal])];
-            
-            layout.delegate = self;
-        } else {
-            _collectionViewlayout = [UICollectionViewLayout new];
-        }
-        
-        _dataController = [WXRecyclerDataController new];
-        _updateController = [WXRecyclerUpdateController new];
-        _updateController.delegate = self;
-        [self fixFlicker];
-        
-        if ([attributes[@"draggable"] boolValue]) {
-            // lazy load
-            _dragController = [WXRecyclerDragController new];
-            _dragController.delegate = self;
-            if([attributes[@"dragTriggerType"]  isEqual: @"pan"]){
-                _dragController.dragTriggerType = WXRecyclerDragTriggerPan;
-            }
-            _dragController.isDragable = YES;
-        }
-    }
-    
-    return self;
-}
-
-- (void)dealloc
-{
-    _collectionView.delegate = nil;
-    _collectionView.dataSource = nil;
-}
-
-#pragma mark - Public Subclass Methods
-
-- (UIView *)loadView
-{
-    return [[WXCollectionView alloc] initWithFrame:CGRectZero 
collectionViewLayout:_collectionViewlayout];
-}
-
-- (void)viewDidLoad
-{
-    [super viewDidLoad];
-    
-    _collectionView = (UICollectionView *)self.view;
-    _collectionView.allowsSelection = NO;
-    _collectionView.allowsMultipleSelection = NO;
-    _collectionView.dataSource = self;
-    _collectionView.delegate = self;
-    
-    [_collectionView registerClass:[WXCollectionViewCell class] 
forCellWithReuseIdentifier:kCollectionCellReuseIdentifier];
-    [_collectionView registerClass:[UICollectionReusableView class] 
forSupplementaryViewOfKind:kCollectionSupplementaryViewKindHeader 
withReuseIdentifier:kCollectionHeaderReuseIdentifier];
-    
-    _dragController.dragingCell = [[WXCollectionViewCell alloc] 
initWithFrame:CGRectMake(0, 0, 100, 100/2.0f)];
-    _dragController.collectionView = _collectionView;
-    
-    [self performUpdatesWithCompletion:^(BOOL finished) {
-        
-    }];
-}
-
-- (void)viewWillUnload
-{
-    [super viewWillUnload];
-    
-    _collectionView.dataSource = nil;
-    _collectionView.delegate = nil;
-}
-
-- (void)updateAttributes:(NSDictionary *)attributes
-{
-    [super updateAttributes:attributes];
-    
-    if (_layoutType == WXRecyclerLayoutTypeMultiColumn) {
-        CGFloat scaleFactor = self.weexInstance.pixelScaleFactor;
-        WXMultiColumnLayout *layout = (WXMultiColumnLayout 
*)_collectionViewlayout;
-        BOOL needUpdateLayout = NO;
-        
-        if ([attributes[@"draggable"] boolValue]) {
-            if (!_dragController) {  // lazy load
-                _dragController = [WXRecyclerDragController new];
-                _dragController.delegate = self;
-            }
-            if([attributes[@"dragTriggerType"]  isEqual: @"pan"]){
-                _dragController.dragTriggerType = WXRecyclerDragTriggerPan;
-            }
-            _dragController.isDragable = YES;
-        } else {
-            _dragController.isDragable = NO;
-        }
-        
-        if (attributes[@"columnWidth"]) {
-            layout.columnWidth = [WXConvert 
WXLength:attributes[@"columnWidth"] isFloat:YES scaleFactor:scaleFactor];
-            needUpdateLayout = YES;
-        }
-        
-        if (attributes[@"columnCount"]) {
-            layout.columnCount = [WXConvert 
WXLength:attributes[@"columnCount"] isFloat:NO scaleFactor:1.0];
-            
-            needUpdateLayout = YES;
-        }
-        if (attributes[@"columnGap"]) {
-            layout.columnGap = [self _floatValueForColumnGap:([WXConvert 
WXLength:attributes[@"columnGap"] isFloat:YES scaleFactor:scaleFactor])];
-            needUpdateLayout = YES;
-        }
-        if (attributes[@"leftGap"]) {
-            layout.leftGap = [WXConvert WXPixelType:attributes[@"leftGap"] 
scaleFactor:scaleFactor];
-        }
-        if (attributes[@"rightGap"]) {
-            layout.rightGap = [WXConvert WXPixelType:attributes[@"rightGap"] 
scaleFactor:scaleFactor];
-        }
-        
-        if (needUpdateLayout) {
-            for (WXComponent *component in self.subcomponents) {
-                [component setNeedsLayout];
-            }
-            
-            [self.collectionView reloadData];
-            [self.collectionView.collectionViewLayout invalidateLayout];
-        }
-    }
-    
-}
-
-- (void)setContentSize:(CGSize)contentSize
-{
-    // Do Nothing
-}
-
-- (void)adjustSticky
-{
-    // Do Nothing, sticky is adjusted by layout
-}
-
-#pragma mark - Private Subclass Methods
-
-- (void)_updateStylesOnComponentThread:(NSDictionary *)styles 
resetStyles:(NSMutableArray *)resetStyles isUpdateStyles:(BOOL)isUpdateStyles
-{
-    [super _updateStylesOnComponentThread:styles resetStyles:resetStyles 
isUpdateStyles:isUpdateStyles];
-    
-    [self _fillPadding];
-}
-
-- (void)_handleFirstScreenTime
-{
-    // Do Nothing, firstScreenTime is set by cellDidRendered:
-}
-
-- (void)scrollToComponent:(WXComponent *)component withOffset:(CGFloat)offset 
animated:(BOOL)animated
-{
-    CGPoint contentOffset = _collectionView.contentOffset;
-    CGFloat contentOffsetY = 0;
-    
-    CGRect rect;
-    while (component) {
-        if ([component isKindOfClass:[WXCellComponent class]]) {
-            NSIndexPath *toIndexPath = [self.dataController 
indexPathForCell:(WXCellComponent *)component];
-            UICollectionViewLayoutAttributes *attributes = [_collectionView 
layoutAttributesForItemAtIndexPath:toIndexPath];
-            rect = attributes.frame;
-            break;
-        }
-        if ([component isKindOfClass:[WXHeaderComponent class]]) {
-            NSUInteger toIndex = [self.dataController 
indexForHeader:(WXHeaderComponent *)component];
-            UICollectionViewLayoutAttributes *attributes = [_collectionView 
layoutAttributesForSupplementaryElementOfKind:kCollectionSupplementaryViewKindHeader
 atIndexPath:[NSIndexPath indexPathWithIndex:toIndex]];
-            rect = attributes.frame;
-            break;
-        }
-        contentOffsetY += component.calculatedFrame.origin.y;
-        component = component.supercomponent;
-    }
-    
-    contentOffsetY += rect.origin.y;
-    contentOffsetY += offset * self.weexInstance.pixelScaleFactor;
-    
-    if (_collectionView.contentSize.height >= 
_collectionView.frame.size.height && contentOffsetY > 
_collectionView.contentSize.height - _collectionView.frame.size.height) {
-        contentOffset.y = _collectionView.contentSize.height - 
_collectionView.frame.size.height;
-    } else {
-        contentOffset.y = contentOffsetY;
-    }
-    
-    [_collectionView setContentOffset:contentOffset animated:animated];
-    
-}
-
-- (void)performUpdatesWithCompletion:(void (^)(BOOL finished))completion
-{
-    WXAssertMainThread();
-    
-    //TODO: support completion
-    
-    if (![self isViewLoaded]) {
-        completion(NO);
-    }
-    
-    NSArray *oldData = [self.dataController.sections copy];
-    NSArray *newData = [self _sectionArrayFromComponents:self.subcomponents];
-    
-    [_updateController performUpdatesWithNewData:newData oldData:oldData 
view:_collectionView];
-}
-
-- (void)_insertSubcomponent:(WXComponent *)subcomponent 
atIndex:(NSInteger)index
-{
-    if ([subcomponent isKindOfClass:[WXCellComponent class]]) {
-        ((WXCellComponent *)subcomponent).delegate = self;
-    } else if ([subcomponent isKindOfClass:[WXHeaderComponent class]]) {
-        ((WXHeaderComponent *)subcomponent).delegate = self;
-    }
-    
-    [super _insertSubcomponent:subcomponent atIndex:index];
-    
-    if (![subcomponent isKindOfClass:[WXHeaderComponent class]]
-        && ![subcomponent isKindOfClass:[WXCellComponent class]]) {
-        return;
-    }
-    
-    WXPerformBlockOnMainThread(^{
-        [self performUpdatesWithCompletion:^(BOOL finished) {
-            
-        }];
-    });
-}
-
-- (void)insertSubview:(WXComponent *)subcomponent atIndex:(NSInteger)index
-{
-    //Here will not insert cell/header/footer's view again
-    if (![subcomponent isKindOfClass:[WXCellComponent class]]
-        && ![subcomponent isKindOfClass:[WXHeaderComponent class]]
-        && ![subcomponent isKindOfClass:[WXFooterComponent class]]) {
-        [super insertSubview:subcomponent atIndex:index];
-    }
-}
-
-#pragma mark - WXRecyclerUpdateControllerDelegate
-
-- (void)updateController:(WXRecyclerUpdateController *)controller 
willPerformUpdateWithNewData:(NSArray<WXSectionDataController *> *)newData
-{
-    if (newData) {
-        [self.dataController updateData:newData];
-    }
-}
-
-- (void)updateController:(WXRecyclerUpdateController *)controller 
didPerformUpdateWithFinished:(BOOL)finished
-{
-    
-}
-
-#pragma mark - UICollectionViewDataSource
-
-- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView 
*)collectionView
-{
-    WXLogDebug(@"section number:%li", (long)[self.dataController 
numberOfSections]);
-    return [self.dataController numberOfSections];
-}
-
-- (NSInteger)collectionView:(UICollectionView *)collectionView 
numberOfItemsInSection:(NSInteger)section
-{
-    NSInteger numberOfItems = [self.dataController 
numberOfItemsInSection:section];
-    
-    WXLogDebug(@"Number of items is %ld in section:%ld", (long)numberOfItems, 
(long)section);
-    
-    return numberOfItems;
-}
-
-- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView 
cellForItemAtIndexPath:(NSIndexPath *)indexPath
-{
-    WXLogDebug(@"Getting cell at indexPath:%@", indexPath);
-    
-    WXCollectionViewCell *cellView = [_collectionView 
dequeueReusableCellWithReuseIdentifier:kCollectionCellReuseIdentifier 
forIndexPath:indexPath];
-    
-    UIView *contentView = [self.dataController 
cellForItemAtIndexPath:indexPath];
-    
-    cellView.wx_component = contentView.wx_component;
-    
-    [self.dragController goThroughAnchor:cellView.wx_component 
indexPath:indexPath];
-    
-    if (contentView.superview == cellView.contentView) {
-        return cellView;
-    }
-    
-    for (UIView *view in cellView.contentView.subviews) {
-        [view removeFromSuperview];
-    }
-    
-    [cellView.contentView addSubview:contentView];
-    [cellView setAccessibilityIdentifier:contentView.accessibilityIdentifier];
-    
-    return cellView;
-}
-
-- (UICollectionReusableView *)collectionView:(UICollectionView 
*)collectionView viewForSupplementaryElementOfKind:(NSString *)kind 
atIndexPath:(NSIndexPath *)indexPath
-{
-    UICollectionReusableView *reusableView = nil;
-    if ([kind isEqualToString:kCollectionSupplementaryViewKindHeader]) {
-        reusableView = [collectionView 
dequeueReusableSupplementaryViewOfKind:kind 
withReuseIdentifier:kCollectionHeaderReuseIdentifier forIndexPath:indexPath];
-        UIView *contentView = [self.dataController 
viewForHeaderAtIndexPath:indexPath];
-        if (contentView.superview != reusableView) {
-            for (UIView *view in reusableView.subviews) {
-                [view removeFromSuperview];
-            }
-            
-            [reusableView addSubview:contentView];
-        }
-    }
-    
-    return reusableView;
-}
-
-#pragma mark - UICollectionViewDelegate
-
-- (void)collectionView:(UICollectionView *)collectionView 
willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath 
*)indexPath
-{
-    WXLogDebug(@"will display cell:%@, at index path:%@", cell, indexPath);
-}
-
-- (void)collectionView:(UICollectionView *)collectionView 
didEndDisplayingCell:(UICollectionViewCell *)cell 
forItemAtIndexPath:(NSIndexPath *)indexPath
-{
-    WXLogDebug(@"Did end displaying cell:%@, at index path:%@", cell, 
indexPath);
-}
-
-#pragma mark - WXMultiColumnLayoutDelegate
-
-- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView 
insetForLayout:(UICollectionViewLayout *)collectionViewLayout
-{
-    return _padding;
-}
-
-- (CGFloat)collectionView:(UICollectionView *)collectionView 
contentWidthForLayout:(UICollectionViewLayout *)collectionViewLayout
-{
-    return self.scrollerCSSNode->style.dimensions[CSS_WIDTH];
-}
-
-- (CGFloat)collectionView:(UICollectionView *)collectionView 
layout:(UICollectionViewLayout *)collectionViewLayout 
heightForItemAtIndexPath:(NSIndexPath *)indexPath
-{
-    CGSize itemSize = [self.dataController sizeForItemAtIndexPath:indexPath];
-    return itemSize.height;
-}
-
-- (CGFloat)collectionView:(UICollectionView *)collectionView 
layout:(UICollectionViewLayout *)collectionViewLayout 
heightForHeaderInSection:(NSInteger)section
-{
-    CGSize headerSize = [self.dataController 
sizeForHeaderAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:section]];
-    return headerSize.height;
-}
-
-- (BOOL)collectionView:(UICollectionView *)collectionView 
layout:(UICollectionViewLayout *)collectionViewLayout 
hasHeaderInSection:(NSInteger)section
-{
-    return [self.dataController hasHeaderInSection:section];
-}
-
-- (CGFloat)collectionView:(UICollectionView *)collectionView 
layout:(UICollectionViewLayout *)collectionViewLayout 
isNeedStickyForHeaderInSection:(NSInteger)section
-{
-    return [self.dataController isStickyForHeaderAtIndexPath:[NSIndexPath 
indexPathForItem:0 inSection:section]];
-}
-
-#pragma mark - WXHeaderRenderDelegate
-
-- (float)headerWidthForLayout:(WXHeaderComponent *)header
-{
-    if (_layoutType == WXRecyclerLayoutTypeMultiColumn) {
-        return ((WXMultiColumnLayout 
*)_collectionViewlayout).computedHeaderWidth;
-    }
-    
-    return 0.0;
-}
-
-- (void)headerDidLayout:(WXHeaderComponent *)header
-{
-    WXPerformBlockOnMainThread(^{
-        [self.collectionView.collectionViewLayout invalidateLayout];
-    });
-}
-
-- (void)headerDidRemove:(WXHeaderComponent *)header
-{
-    WXPerformBlockOnMainThread(^{
-        [self performUpdatesWithCompletion:^(BOOL finished) {
-            
-        }];
-    });
-}
-
-#pragma mark - WXCellRenderDelegate
-
-- (float)containerWidthForLayout:(WXCellComponent *)cell
-{
-    if (_layoutType == WXRecyclerLayoutTypeMultiColumn) {
-        return ((WXMultiColumnLayout 
*)_collectionViewlayout).computedColumnWidth;
-    }
-    
-    return 0.0;
-}
-
-- (void)cellDidLayout:(WXCellComponent *)cell
-{
-    BOOL previousLayoutComplete = cell.isLayoutComplete;
-    cell.isLayoutComplete = YES;
-    WXPerformBlockOnMainThread(^{
-        if (previousLayoutComplete) {
-            [self.updateController reloadItemsAtIndexPath:[self.dataController 
indexPathForCell:cell]];
-        } else {
-            [self performUpdatesWithCompletion:^(BOOL finished) {
-            }];
-        }
-    });
-}
-
-- (void)cellDidRendered:(WXCellComponent *)cell
-{
-    if (WX_MONITOR_INSTANCE_PERF_IS_RECORDED(WXPTFirstScreenRender, 
self.weexInstance) && !self.weexInstance.onRenderProgress) {
-        return;
-    }
-    
-    NSIndexPath *indexPath = [self.dataController indexPathForCell:cell];
-    
-    UICollectionViewLayoutAttributes *attributes = [self.collectionView 
layoutAttributesForItemAtIndexPath:indexPath];
-    CGRect cellRect = attributes.frame;
-    if (cellRect.origin.y + cellRect.size.height >= 
_collectionView.frame.size.height) {
-        WX_MONITOR_INSTANCE_PERF_END(WXPTFirstScreenRender, self.weexInstance);
-    }
-    
-    if (self.weexInstance.onRenderProgress) {
-        CGRect renderRect = [_collectionView convertRect:cellRect 
toView:self.weexInstance.rootView];
-        self.weexInstance.onRenderProgress(renderRect);
-    }
-}
-
-- (void)cellDidRemove:(WXCellComponent *)cell
-{
-    if (cell.isLayoutComplete) {
-        WXPerformBlockOnMainThread(^{
-            [self performUpdatesWithCompletion:^(BOOL finished) {
-            }];
-        });
-    }
-}
-
-- (void)cell:(WXCellComponent *)cell didMoveToIndex:(NSUInteger)index
-{
-    if (cell.isLayoutComplete) {
-        WXPerformBlockOnMainThread(^{
-            [self performUpdatesWithCompletion:^(BOOL finished) {
-            }];
-        });
-    }
-}
-
-#pragma mark - Load More Event
-
-- (void)setLoadmoreretry:(NSUInteger)loadmoreretry
-{
-    if (loadmoreretry != self.loadmoreretry) {
-        _previousLoadMoreCellNumber = 0;
-    }
-    
-    [super setLoadmoreretry:loadmoreretry];
-}
-
-- (void)loadMore
-{
-    [super loadMore];
-    
-    _previousLoadMoreCellNumber = [self totalNumberOfCells];
-}
-
-- (BOOL)isNeedLoadMore
-{
-    BOOL superNeedLoadMore = [super isNeedLoadMore];
-    return superNeedLoadMore && _previousLoadMoreCellNumber != [self 
totalNumberOfCells];
-}
-
-- (NSUInteger)totalNumberOfCells
-{
-    NSUInteger cellNumber = 0;
-    NSUInteger sectionCount = [_collectionView numberOfSections];
-    for (int section = 0; section < sectionCount; section ++) {
-        cellNumber += [_collectionView numberOfItemsInSection:section];
-    }
-    
-    return cellNumber;
-}
-
-- (void)resetLoadmore{
-    [super resetLoadmore];
-    _previousLoadMoreCellNumber = 0;
-}
-
-#pragma mark - Private
-
-- (float)_floatValueForColumnGap:(WXLength *)gap
-{
-    if (gap.isNormal) {
-        return kRecyclerNormalColumnGap * self.weexInstance.pixelScaleFactor;
-    } else {
-        return gap.floatValue;
-    }
-}
-
-- (void)_fillPadding
-{
-    UIEdgeInsets padding = {
-        WXFloorPixelValue(self.cssNode->style.padding[CSS_TOP] + 
self.cssNode->style.border[CSS_TOP]),
-        WXFloorPixelValue(self.cssNode->style.padding[CSS_LEFT] + 
self.cssNode->style.border[CSS_LEFT]),
-        WXFloorPixelValue(self.cssNode->style.padding[CSS_BOTTOM] + 
self.cssNode->style.border[CSS_BOTTOM]),
-        WXFloorPixelValue(self.cssNode->style.padding[CSS_RIGHT] + 
self.cssNode->style.border[CSS_RIGHT])
-    };
-    
-    if (!UIEdgeInsetsEqualToEdgeInsets(padding, _padding)) {
-        _padding = padding;
-        [self setNeedsLayout];
-        
-        for (WXComponent *component in self.subcomponents) {
-            [component setNeedsLayout];
-        }
-        
-        if (_collectionView) {
-            WXPerformBlockOnMainThread(^{
-                [_collectionView.collectionViewLayout invalidateLayout];
-            });
-        }
-    }
-}
-
-- (NSArray<WXSectionDataController *> 
*)_sectionArrayFromComponents:(NSArray<WXComponent *> *)components
-{
-    NSMutableArray<WXSectionDataController *> *sectionArray = [NSMutableArray 
array];
-    NSMutableArray<WXCellComponent *> *cellArray = [NSMutableArray array];
-    WXSectionDataController *currentSection;
-    
-    for (int i = 0; i < components.count; i++) {
-        if (!currentSection) {
-            currentSection = [WXSectionDataController new];
-        }
-        
-        WXComponent* component = components[i];
-        
-        if ([component isKindOfClass:[WXHeaderComponent class]]) {
-            if (i != 0 && (currentSection.headerComponent || cellArray.count > 
0)) {
-                currentSection.cellComponents = [cellArray copy];
-                [sectionArray addObject:currentSection];
-                currentSection = [WXSectionDataController new];
-                [cellArray removeAllObjects];
-            }
-            currentSection.headerComponent = (WXHeaderComponent *)component;
-        } else if ([component isKindOfClass:[WXCellComponent class]]
-                   && ((WXCellComponent *)component).isLayoutComplete) {
-            [cellArray addObject:(WXCellComponent *)component];
-        } else if ([component isKindOfClass:[WXFooterComponent class]]) {
-            currentSection.footerComponent = component;
-        } else {
-            continue;
-        }
-    }
-    
-    if (cellArray.count > 0 || currentSection.headerComponent) {
-        currentSection.cellComponents = [cellArray copy];
-        [sectionArray addObject:currentSection];
-    }
-    
-    return sectionArray;
-}
-
-- (void)fixFlicker
-{
-    static dispatch_once_t onceToken;
-    dispatch_once(&onceToken, ^{
-        // FIXME:(ง •̀_•́)ง┻━┻ 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";
-        
-        NSString *originSelector = [NSString stringWithFormat:@"_%@%@cessary", 
b, a];
-        [[self class] weex_swizzle:[WXCollectionView class] 
Method:NSSelectorFromString(originSelector) 
withMethod:@selector(fixedFlickerSelector)];
-    });
-}
-
-#define mark dragControllerDelegate
-
-- (void)updateDataSource{
-    NSMutableArray *oldComponents = [[NSMutableArray alloc] 
initWithArray:self.dataController.sections[self.dragController.startIndexPath.section].cellComponents];
-    if(oldComponents.count > 1){
-        WXCellComponent *startComponent = 
self.dataController.sections[self.dragController.startIndexPath.section].cellComponents[self.dragController.startIndexPath.item];
-        [oldComponents removeObject:startComponent];
-        [oldComponents insertObject:startComponent 
atIndex:self.dragController.targetIndexPath.item];
-        
self.dataController.sections[self.dragController.startIndexPath.section].cellComponents
 = oldComponents;
-    }
-}
-
-- (void)dragFireEvent:(NSString *)eventName params:(NSDictionary *)params{
-    [self fireEvent:eventName params:params];
-}
-
-- (void)fixedFlickerSelector
-{
-    // DO NOT delete this method.
-}
-
-@end


Reply via email to