You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by cx...@apache.org on 2017/03/02 03:28:47 UTC

[13/25] incubator-weex git commit: * [ios] support cell move and remove and reload

* [ios] support cell move and remove and reload


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

Branch: refs/heads/0.11-dev-recycler
Commit: 0ce0cb50166e220058696e52a70cfeb6455cae86
Parents: 4c8127c
Author: \u9690\u98ce <cx...@gmail.com>
Authored: Fri Feb 24 14:42:58 2017 +0800
Committer: \u9690\u98ce <cx...@gmail.com>
Committed: Fri Feb 24 14:42:58 2017 +0800

----------------------------------------------------------------------
 examples/vue/components/waterfall.vue           | 47 +++++++++++++++-----
 .../Component/Recycler/WXRecyclerComponent.m    | 35 ++++++++++-----
 .../Recycler/WXRecyclerDataController.m         |  2 -
 .../Recycler/WXRecyclerUpdateController.h       |  3 ++
 .../Recycler/WXRecyclerUpdateController.m       | 22 +++++++--
 .../Recycler/WXSectionDataController.h          |  3 +-
 .../Recycler/WXSectionDataController.m          |  6 +--
 .../WeexSDK/Sources/Component/WXCellComponent.h |  5 ++-
 .../WeexSDK/Sources/Component/WXCellComponent.m | 12 +++--
 .../Sources/Component/WXHeaderComponent.h       |  6 ++-
 .../Sources/Component/WXHeaderComponent.m       |  8 +++-
 .../WeexSDK/Sources/Component/WXListComponent.m |  2 +-
 ios/sdk/WeexSDK/Sources/Model/WXComponent.m     |  2 +-
 ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.h    |  8 +++-
 ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m    | 25 ++++++++++-
 15 files changed, 140 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/0ce0cb50/examples/vue/components/waterfall.vue
----------------------------------------------------------------------
diff --git a/examples/vue/components/waterfall.vue b/examples/vue/components/waterfall.vue
index fe6cd91..ac34919 100644
--- a/examples/vue/components/waterfall.vue
+++ b/examples/vue/components/waterfall.vue
@@ -5,7 +5,7 @@
   :show-scrollbar="showScrollbar" :scrollable="scrollable"
   @scroll="recylerScroll"
   >
-    <header class="header" ref="header">
+    <header class="header" ref="header" v-if="showHeader">
       <image class="banner" src="https://gw.alicdn.com/tps/TB1ESN1PFXXXXX1apXXXXXXXXXX-1000-600.jpg" resize="cover">
         <div class="bannerInfo">
           <image class="avatar" src="https://gw.alicdn.com/tps/TB1EP9bPFXXXXbpXVXXXXXXXXXX-150-110.jpg" resize="cover"></image>
@@ -19,7 +19,7 @@
         </div>
       </image>
     </header>
-    <header class="stickyHeader">
+    <header class="stickyHeader" @click="showOrRemoveHeader">
       <div v-if="stickyHeaderType === 'none'" class="stickyWrapper">
         <text class="stickyText">Sticky Header</text>
       </div>
@@ -37,8 +37,8 @@
         <text class="stickyText">Content Offset:{{contentOffset}}</text>
       </div>
     </header>
-    <cell v-for="item in items" class="cell">
-      <div class="item" @click="onItemclick(item.behaviour)" @appear="itemAppear(item.src)" @disappear="itemDisappear(item.src)">
+    <cell v-for="(item, index) in items" :key="item.src" class="cell">
+      <div class="item" @click="onItemclick(item.behaviour, index)" @appear="itemAppear(item.src)" @disappear="itemDisappear(item.src)">
         <text v-if="item.name" class="itemName">{{item.name}}</text>
         <image class="itemPhoto" :src="item.src"></image>
         <text v-if="item.desc" class="itemDesc">{{item.desc}}</text>
@@ -257,17 +257,19 @@
         },
         {
           src:'https://gw.alicdn.com/tps/TB1ux2vPFXXXXbkXXXXXXXXXXXX-240-240.jpg',
-          behaviourName: 'listen scroll',
-          behaviour: 'listenScroll',
+          behaviourName: 'Remove cell',
+          behaviour: 'removeCell',
         },
         {
-          src:'https://gw.alicdn.com/tps/TB1tCCWPFXXXXa7aXXXXXXXXXXX-240-240.jpg'
+          src:'https://gw.alicdn.com/tps/TB1tCCWPFXXXXa7aXXXXXXXXXXX-240-240.jpg',
+          behaviourName: 'Move cell',
+          behaviour: 'moveCell',
         }
       ]
 
       let repeatItems = [];
-      for (let i = 0; i < 5; i++) {
-        repeatItems.push(...items);
+      for (let i = 0; i < 3; i++) {
+        repeatItems.push(...items)
       }
 
       return {
@@ -276,6 +278,7 @@
         columnGap: 12,
         columnWidth: 'auto',
         contentOffset: '0',
+        showHeader: true,
         showScrollbar: false,
         scrollable: true,
         showStickyHeader: false,
@@ -300,8 +303,11 @@
       recylerScroll: function(e) {
         this.contentOffset = e.contentOffset.y
       },
-      onItemclick: function (behaviour) {
-        console.log(`click...${behaviour}`)
+      showOrRemoveHeader: function() {
+        this.showHeader = !this.showHeader
+      },
+      onItemclick: function (behaviour, index) {
+        console.log(`click...${behaviour} at index ${index}`)
         switch (behaviour) {
           case 'changeColumnCount':
             this.changeColumnCount()
@@ -326,6 +332,13 @@
             break
           case 'listenScroll':
             this.listenScrollEvent()
+            break
+          case 'removeCell':
+            this.removeCell(index)
+            break
+          case 'moveCell':
+            this.moveCell(index)
+            break
         }
       },
 
@@ -383,6 +396,18 @@
 
       setRecyclerPadding: function() {
         this.padding = (this.padding == 0 ? 12 : 0);
+      },
+
+      removeCell: function(index) {
+        this.items.splice(index, 1)
+      },
+
+      moveCell: function(index) {
+        if (index == 0) {
+          this.items.splice(this.items.length - 1, 0, this.items.splice(index, 1)[0]);
+        } else {
+          this.items.splice(0, 0, this.items.splice(index, 1)[0]);
+        }
       }
     }
   }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/0ce0cb50/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
index d7e1fac..7dffe8c 100644
--- a/ios/sdk/WeexSDK/Sources/Component/Recycler/WXRecyclerComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/Recycler/WXRecyclerComponent.m
@@ -214,6 +214,8 @@ typedef enum : NSUInteger {
 {
     WXAssertMainThread();
     
+    //TODO: support completion
+    
     if (![self isViewLoaded]) {
         completion(NO);
     }
@@ -261,7 +263,9 @@ typedef enum : NSUInteger {
 
 - (void)updateController:(WXRecyclerUpdateController *)controller willPerformUpdateWithNewData:(NSArray<WXSectionDataController *> *)newData
 {
-    [self.dataController updateData:newData];
+    if (newData) {
+        [self.dataController updateData:newData];
+    }
 }
 
 - (void)updateController:(WXRecyclerUpdateController *)controller didPerformUpdateWithFinished:(BOOL)finished
@@ -370,7 +374,7 @@ typedef enum : NSUInteger {
 
 #pragma mark - WXHeaderRenderDelegate
 
-- (float)headerWidthForLayout:(WXHeaderComponent *)cell
+- (float)headerWidthForLayout:(WXHeaderComponent *)header
 {
     if (_layoutType == WXRecyclerLayoutTypeMultiColumn) {
         return ((WXMultiColumnLayout *)_collectionViewlayout).computedHeaderWidth;
@@ -379,16 +383,25 @@ typedef enum : NSUInteger {
     return 0.0;
 }
 
-- (void)headerDidLayout:(WXHeaderComponent *)cell
+- (void)headerDidLayout:(WXHeaderComponent *)header
 {
     WXPerformBlockOnMainThread(^{
         [self.collectionView.collectionViewLayout invalidateLayout];
     });
 }
 
+- (void)headerDidRemove:(WXHeaderComponent *)header
+{
+    WXPerformBlockOnMainThread(^{
+        [self performUpdatesWithCompletion:^(BOOL finished) {
+            
+        }];
+    });
+}
+
 #pragma mark - WXCellRenderDelegate
 
-- (float)cellWidthForLayout:(WXCellComponent *)cell
+- (float)containerWidthForLayout:(WXCellComponent *)cell
 {
     if (_layoutType == WXRecyclerLayoutTypeMultiColumn) {
         return ((WXMultiColumnLayout *)_collectionViewlayout).computedColumnWidth;
@@ -399,11 +412,15 @@ typedef enum : NSUInteger {
 
 - (void)cellDidLayout:(WXCellComponent *)cell
 {
+    BOOL previousLayoutComplete = cell.isLayoutComplete;
     cell.isLayoutComplete = YES;
     WXPerformBlockOnMainThread(^{
-        [self.collectionView.collectionViewLayout invalidateLayout];
-        [self performUpdatesWithCompletion:^(BOOL finished) {
-        }];
+        if (previousLayoutComplete) {
+            [self.updateController reloadItemsAtIndexPath:[self.dataController indexPathForCell:cell]];
+        } else {
+            [self performUpdatesWithCompletion:^(BOOL finished) {
+            }];
+        }
     });
 }
 
@@ -416,7 +433,6 @@ typedef enum : NSUInteger {
 {
     if (cell.isLayoutComplete) {
         WXPerformBlockOnMainThread(^{
-            [self.collectionView.collectionViewLayout invalidateLayout];
             [self performUpdatesWithCompletion:^(BOOL finished) {
             }];
         });
@@ -427,7 +443,6 @@ typedef enum : NSUInteger {
 {
     if (cell.isLayoutComplete) {
         WXPerformBlockOnMainThread(^{
-            [self.collectionView.collectionViewLayout invalidateLayout];
             [self performUpdatesWithCompletion:^(BOOL finished) {
             }];
         });
@@ -499,7 +514,7 @@ typedef enum : NSUInteger {
         }
         
         if (i == components.count - 1 && cellArray.count > 0) {
-            currentSection.cellComponents = cellArray;
+            currentSection.cellComponents = [cellArray copy];
             [sectionArray addObject:currentSection];
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/0ce0cb50/ios/sdk/WeexSDK/Sources/Component/Recycler/WXRecyclerDataController.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/Recycler/WXRecyclerDataController.m b/ios/sdk/WeexSDK/Sources/Component/Recycler/WXRecyclerDataController.m
index c75987c..aa5732d 100644
--- a/ios/sdk/WeexSDK/Sources/Component/Recycler/WXRecyclerDataController.m
+++ b/ios/sdk/WeexSDK/Sources/Component/Recycler/WXRecyclerDataController.m
@@ -14,8 +14,6 @@
 @interface WXRecyclerDataController ()
 
 @property (nonatomic, strong, readwrite) NSArray<WXSectionDataController *> *sections;
-@property (nonatomic, strong, readonly) NSMapTable<WXSectionDataController *, NSNumber *> *sectionControllerToSectionIndexTable;
-@property (nonatomic, strong, readonly) NSMapTable<NSNumber *, WXSectionDataController *> *sectionToSectionControllerIndexTable;
 @property (nonatomic, strong, readonly) NSMapTable<WXCellComponent *, NSIndexPath*> *cellToIndexPathTable;
 
 @end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/0ce0cb50/ios/sdk/WeexSDK/Sources/Component/Recycler/WXRecyclerUpdateController.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/Recycler/WXRecyclerUpdateController.h b/ios/sdk/WeexSDK/Sources/Component/Recycler/WXRecyclerUpdateController.h
index c015c09..e376c19 100644
--- a/ios/sdk/WeexSDK/Sources/Component/Recycler/WXRecyclerUpdateController.h
+++ b/ios/sdk/WeexSDK/Sources/Component/Recycler/WXRecyclerUpdateController.h
@@ -25,5 +25,8 @@
 - (void)performUpdatesWithNewData:(NSArray<WXSectionDataController *> *)newData
                           oldData:(NSArray<WXSectionDataController *> *)oldData
                              view:(UICollectionView *)collectionView;
+
+- (void)reloadItemsAtIndexPath:(NSIndexPath *)indexPath;
+
 @end
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/0ce0cb50/ios/sdk/WeexSDK/Sources/Component/Recycler/WXRecyclerUpdateController.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/Recycler/WXRecyclerUpdateController.m b/ios/sdk/WeexSDK/Sources/Component/Recycler/WXRecyclerUpdateController.m
index ae521ea..17090b0 100644
--- a/ios/sdk/WeexSDK/Sources/Component/Recycler/WXRecyclerUpdateController.m
+++ b/ios/sdk/WeexSDK/Sources/Component/Recycler/WXRecyclerUpdateController.m
@@ -65,6 +65,7 @@
 @property (nonatomic, copy) NSArray<WXSectionDataController *> *theNewData;
 @property (nonatomic, copy) NSArray<WXSectionDataController *> *theOldData;
 @property (nonatomic, weak) UICollectionView *collectionView;
+@property (nonatomic, strong) NSMutableSet<NSIndexPath *> *reloadIndexPaths;
 @property (nonatomic, assign) BOOL isUpdating;
 
 @end
@@ -84,10 +85,21 @@
     [self checkUpdates];
 }
 
+- (void)reloadItemsAtIndexPath:(NSIndexPath *)indexPath
+{
+    if (!_reloadIndexPaths) {
+        _reloadIndexPaths = [NSMutableSet set];
+    }
+    
+    [_reloadIndexPaths addObject:indexPath];
+    
+    [self checkUpdates];
+}
+
 - (void)checkUpdates
 {
     dispatch_async(dispatch_get_main_queue(), ^{
-        if (self.isUpdating || (!self.theOldData && !self.theNewData)) {
+        if (self.isUpdating) {
             return ;
         }
         
@@ -111,7 +123,7 @@
     [self cleanup];
     
     WXRecyclerDiffResult *diffResult = [self diffWithNewData:newData oldData:oldData];
-    if (![diffResult hasChanges]) {
+    if (![diffResult hasChanges] && self.reloadIndexPaths.count == 0) {
         return;
     }
     
@@ -125,6 +137,7 @@
         [UIView setAnimationsEnabled:YES];
         self.isUpdating = NO;
         [self.delegate updateController:self didPerformUpdateWithFinished:finished];
+        [self.reloadIndexPaths removeAllObjects];
         [self checkUpdates];
     };
     
@@ -213,7 +226,10 @@
     
     [collectionView deleteItemsAtIndexPaths:[diffResult.deleteIndexPaths allObjects]];
     [collectionView insertItemsAtIndexPaths:[diffResult.insertIndexPaths allObjects]];
-    [collectionView reloadItemsAtIndexPaths:[diffResult.reloadIndexPaths allObjects]];
+    
+    NSSet *reloadIndexPaths = self.reloadIndexPaths ? [diffResult.reloadIndexPaths setByAddingObjectsFromSet:self.reloadIndexPaths] : diffResult.reloadIndexPaths;
+    
+    [collectionView reloadItemsAtIndexPaths:[reloadIndexPaths allObjects]];
     
     [collectionView deleteSections:diffResult.deleteSections];
     [collectionView insertSections:diffResult.insertSections];

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/0ce0cb50/ios/sdk/WeexSDK/Sources/Component/Recycler/WXSectionDataController.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/Recycler/WXSectionDataController.h b/ios/sdk/WeexSDK/Sources/Component/Recycler/WXSectionDataController.h
index d6fe7d6..ae257b3 100644
--- a/ios/sdk/WeexSDK/Sources/Component/Recycler/WXSectionDataController.h
+++ b/ios/sdk/WeexSDK/Sources/Component/Recycler/WXSectionDataController.h
@@ -7,11 +7,12 @@
  */
 
 #import <Foundation/Foundation.h>
+#import "WXDiffUtil.h"
 @class WXComponent;
 @class WXCellComponent;
 @class WXHeaderComponent;
 
-@interface WXSectionDataController : NSObject
+@interface WXSectionDataController : NSObject <WXDiffable>
 
 @property (nonatomic, strong) NSArray<WXCellComponent *> *cellComponents;
 @property (nonatomic, strong) WXHeaderComponent *headerComponent;

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/0ce0cb50/ios/sdk/WeexSDK/Sources/Component/Recycler/WXSectionDataController.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/Recycler/WXSectionDataController.m b/ios/sdk/WeexSDK/Sources/Component/Recycler/WXSectionDataController.m
index c4270d7..8aaa031 100644
--- a/ios/sdk/WeexSDK/Sources/Component/Recycler/WXSectionDataController.m
+++ b/ios/sdk/WeexSDK/Sources/Component/Recycler/WXSectionDataController.m
@@ -11,10 +11,6 @@
 #import "WXHeaderComponent.h"
 #import "WXAssert.h"
 
-@interface WXSectionDataController ()
-
-@end
-
 @implementation WXSectionDataController
 
 - (NSInteger)numberOfItems
@@ -58,7 +54,7 @@
     return [super hash];
 }
 
-- (BOOL)isEqual:(id)object
+- (BOOL)isEqualToWXObject:(id<WXDiffable>)object
 {
     if ([object isKindOfClass:[WXSectionDataController class]]) {
         WXSectionDataController *controller = (WXSectionDataController *)object;

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/0ce0cb50/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.h b/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.h
index 29aa1c6..d3358fd 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.h
+++ b/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.h
@@ -7,11 +7,12 @@
  */
 
 #import "WXComponent.h"
+#import "WXDiffUtil.h"
 @class WXCellComponent;
 
 @protocol WXCellRenderDelegate <NSObject>
 
-- (float)cellWidthForLayout:(WXCellComponent *)cell;
+- (float)containerWidthForLayout:(WXCellComponent *)cell;
 
 - (void)cellDidLayout:(WXCellComponent *)cell;
 
@@ -23,7 +24,7 @@
 
 @end
 
-@interface WXCellComponent : WXComponent
+@interface WXCellComponent : WXComponent <WXDiffable>
 
 @property (nonatomic, strong) NSString *scope;
 @property (nonatomic, assign) BOOL isRecycle;

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/0ce0cb50/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m
index 593628a..652754e 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m
@@ -11,6 +11,11 @@
 #import "WXCellComponent.h"
 #import "WXListComponent.h"
 #import "WXComponent_internal.h"
+#import "WXDiffUtil.h"
+
+@interface WXCellComponent ()
+
+@end
 
 @implementation WXCellComponent
 {
@@ -39,10 +44,9 @@
     
 }
 
-- (BOOL)isEqual:(id)object
+- (BOOL)isEqualToWXObject:(id<WXDiffable>)object
 {
-    WXCellComponent *cell = object;
-    return self == cell && self.isLayoutComplete == cell.isLayoutComplete && CGRectEqualToRect(self.calculatedFrame, cell.calculatedFrame);
+    return self == object;
 }
 
 - (void)_frameDidCalculated:(BOOL)isChanged
@@ -110,7 +114,7 @@
 - (void)_calculateFrameWithSuperAbsolutePosition:(CGPoint)superAbsolutePosition gatherDirtyComponents:(NSMutableSet<WXComponent *> *)dirtyComponents
 {
     if (self.delegate && (isUndefined(self.cssNode->style.dimensions[CSS_WIDTH]) || _isUseContainerWidth)) {
-        self.cssNode->style.dimensions[CSS_WIDTH] = [self.delegate cellWidthForLayout:self];
+        self.cssNode->style.dimensions[CSS_WIDTH] = [self.delegate containerWidthForLayout:self];
         //TODO: set _isUseContainerWidth to NO if updateStyles have width
         _isUseContainerWidth = YES;
     }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/0ce0cb50/ios/sdk/WeexSDK/Sources/Component/WXHeaderComponent.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXHeaderComponent.h b/ios/sdk/WeexSDK/Sources/Component/WXHeaderComponent.h
index 5aaf616..1ac21cc 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXHeaderComponent.h
+++ b/ios/sdk/WeexSDK/Sources/Component/WXHeaderComponent.h
@@ -11,9 +11,11 @@
 
 @protocol WXHeaderRenderDelegate <NSObject>
 
-- (float)headerWidthForLayout:(WXHeaderComponent *)cell;
+- (float)headerWidthForLayout:(WXHeaderComponent *)header;
 
-- (void)headerDidLayout:(WXHeaderComponent *)cell;
+- (void)headerDidLayout:(WXHeaderComponent *)header;
+
+- (void)headerDidRemove:(WXHeaderComponent *)header;
 
 @end
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/0ce0cb50/ios/sdk/WeexSDK/Sources/Component/WXHeaderComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXHeaderComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXHeaderComponent.m
index f54938d..33b3040 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXHeaderComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/WXHeaderComponent.m
@@ -14,7 +14,6 @@
     BOOL _isUseContainerWidth;
 }
 
-//TODO: header remove->need reload
 - (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];
@@ -41,6 +40,13 @@
     }
 }
 
+- (void)_removeFromSupercomponent
+{
+    [super _removeFromSupercomponent];
+    
+    [self.delegate headerDidRemove:self];
+}
+
 - (void)_calculateFrameWithSuperAbsolutePosition:(CGPoint)superAbsolutePosition gatherDirtyComponents:(NSMutableSet<WXComponent *> *)dirtyComponents
 {
     if (self.delegate && (isUndefined(self.cssNode->style.dimensions[CSS_WIDTH]) || _isUseContainerWidth)) {

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/0ce0cb50/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 943bcf8..b683f63 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXListComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/WXListComponent.m
@@ -268,7 +268,7 @@
 
 #pragma mark - WXCellRenderDelegate
 
-- (float)cellWidthForLayout:(WXCellComponent *)cell
+- (float)containerWidthForLayout:(WXCellComponent *)cell
 {
     return self.scrollerCSSNode->style.dimensions[CSS_WIDTH];
 }

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/0ce0cb50/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
index 76ca9b0..e10c70d 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
@@ -167,7 +167,7 @@
 
 - (NSString *)description
 {
-    return [NSString stringWithFormat:@"<%@ ref=%@> %@", _type, _ref, _view];
+    return [NSString stringWithFormat:@"<%@:%p ref=%@> %@", _type, self, _ref, _view];
 }
 
 #pragma mark Property

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/0ce0cb50/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.h b/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.h
index c7edda9..e407469 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.h
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.h
@@ -8,6 +8,12 @@
 
 #import <Foundation/Foundation.h>
 
+@protocol WXDiffable <NSObject>
+
+- (BOOL)isEqualToWXObject:(id<WXDiffable>)object;
+
+@end
+
 @interface WXDiffUpdateIndex : NSObject
 
 @property (nonatomic, assign, readonly) NSUInteger oldIndex;
@@ -27,6 +33,6 @@
 
 @interface WXDiffUtil : NSObject
 
-+ (WXDiffResult *)diffWithMinimumDistance:(NSArray *)newArray oldArray:(NSArray *)oldArray;
++ (WXDiffResult *)diffWithMinimumDistance:(NSArray<id<WXDiffable>> *)newArray oldArray:(NSArray<id<WXDiffable>> *)oldArray;
 
 @end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/0ce0cb50/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m b/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m
index 44bd737..01cab02 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m
@@ -7,6 +7,7 @@
  */
 
 #import "WXDiffUtil.h"
+#import "WXLog.h"
 
 typedef enum : NSUInteger {
     WXDiffOperationDoNothing,
@@ -59,7 +60,7 @@ typedef enum : NSUInteger {
 
 @implementation WXDiffUtil
 
-+ (WXDiffResult *)diffWithMinimumDistance:(NSArray *)newArray oldArray:(NSArray *)oldArray
++ (WXDiffResult *)diffWithMinimumDistance:(NSArray<id<WXDiffable>> *)newArray oldArray:(NSArray<id<WXDiffable>> *)oldArray
 {
     // Using the levenshtein algorithm
     // https://en.wikipedia.org/wiki/Levenshtein_distance
@@ -84,7 +85,7 @@ typedef enum : NSUInteger {
     
     for (int oldIndex = 1; oldIndex < oldSize; oldIndex ++) {
         for (int newIndex = 1; newIndex < newSize; newIndex ++) {
-            if ([oldArray[oldIndex - 1] isEqual:newArray[newIndex - 1]]) {
+            if ([oldArray[oldIndex - 1] isEqualToWXObject:newArray[newIndex - 1]]) {
                 matrix[oldIndex][newIndex] = matrix[oldIndex - 1][newIndex - 1];
             } else {
                 int updateCost = matrix[oldIndex - 1][newIndex - 1] + 1;
@@ -95,6 +96,8 @@ typedef enum : NSUInteger {
         }
     }
     
+    [self _printMatrix:matrix rowSize:oldSize columnSize:newSize];
+    
     NSMutableArray *updates = [NSMutableArray array];
     NSMutableIndexSet *inserts = [NSMutableIndexSet indexSet];
     NSMutableIndexSet *deletes = [NSMutableIndexSet indexSet];
@@ -162,4 +165,22 @@ typedef enum : NSUInteger {
     return WXDiffOperationDoNothing;
 }
 
++ (void)_printMatrix:(int **)matrix rowSize:(int)rowSize columnSize:(int)columnSize
+{
+    for (int i = 0; i < rowSize; i ++) {
+        NSMutableArray *array = [NSMutableArray array];
+        for (int j = 0; j < columnSize; j ++) {
+            int value = matrix[i][j];
+            NSString *result;
+            if (value < 10) {
+                result = [NSString stringWithFormat:@"0%zi", value];
+            } else {
+                result = [NSString stringWithFormat:@"%zi", value];
+            }
+            [array addObject:result];
+        }
+        WXLogDebug(@"%@", [array componentsJoinedByString:@" "]);
+    }
+}
+
 @end