Repository: incubator-weex
Updated Branches:
  refs/heads/0.16-dev af2923026 -> 5b99cc6b0


http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.m
----------------------------------------------------------------------
diff --git 
a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.m 
b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.m
new file mode 100644
index 0000000..49ed216
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.m
@@ -0,0 +1,64 @@
+/*
+ * 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 "WXRecycleListDataManager.h"
+#import "NSArray+Weex.h"
+#import "WXLog.h"
+#import "WXAssert.h"
+
+@implementation WXRecycleListDataManager
+{
+    NSArray *_data;
+}
+
+- (instancetype)initWithData:(NSArray *)data
+{
+    if (self = [super init]) {
+        if (![data isKindOfClass:[NSArray class]]) {
+            WXLogError(@"list data must be an array!");
+        } else {
+            _data = data;
+        }
+    }
+    
+    return self;
+}
+
+- (void)updateData:(NSArray *)data
+{
+    WXAssertMainThread();
+    
+    _data = data;
+}
+
+- (NSDictionary *)dataAtIndex:(NSInteger)index
+{
+    WXAssertMainThread();
+    
+    return [_data wx_safeObjectAtIndex:index];
+}
+
+- (NSInteger)numberOfItems
+{
+    WXAssertMainThread();
+    
+    return [_data count];
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.h
----------------------------------------------------------------------
diff --git 
a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.h 
b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.h
new file mode 100644
index 0000000..389dbb8
--- /dev/null
+++ 
b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.h
@@ -0,0 +1,33 @@
+/*
+ * 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 <Foundation/Foundation.h>
+#import "WXCellSlotComponent.h"
+
+@interface WXRecycleListTemplateManager : NSObject
+
+@property (nonatomic, weak) UICollectionView *collectionView;
+
+- (void)addTemplate:(WXCellSlotComponent *)component;
+
+- (WXCellSlotComponent *)dequeueCellSlotWithType:(NSString *)type 
forIndexPath:(NSIndexPath *)indexPath;
+
+- (WXCellSlotComponent *)templateWithType:(NSString *)type;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.m
----------------------------------------------------------------------
diff --git 
a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.m 
b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.m
new file mode 100644
index 0000000..0ac528e
--- /dev/null
+++ 
b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.m
@@ -0,0 +1,94 @@
+/*
+ * 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 "WXRecycleListTemplateManager.h"
+#import "WXLog.h"
+#import "WXAssert.h"
+
+@interface WXReusableCollectionViewCell : UICollectionViewCell
+
+@end
+
+@implementation WXReusableCollectionViewCell
+
+@end
+
+@implementation WXRecycleListTemplateManager
+{
+    NSMapTable<NSString *, WXCellSlotComponent *> *_templateTypeMap;
+}
+
+- (instancetype)init
+{
+    if (self = [super init]) {
+        _templateTypeMap = [NSMapTable strongToWeakObjectsMapTable];
+    }
+    
+    return self;
+}
+
+- (void)setCollectionView:(UICollectionView *)collectionView
+{
+    WXAssertMainThread();
+    
+    if (_collectionView == collectionView) {
+        return;
+    }
+    
+    _collectionView = collectionView;
+    
+    for (NSString *templateType in [_templateTypeMap.keyEnumerator.allObjects 
copy]) {
+        [self _registerCellClassForReuseID:templateType];
+    }
+}
+
+- (void)addTemplate:(WXCellSlotComponent *)component
+{
+    WXAssertMainThread();
+    
+    NSString *templateType = component.templateType;
+    WXAssert(templateType != nil, @"cell-slot:%@ must have a template id!", 
component);
+    
+    [_templateTypeMap setObject:component forKey:templateType];
+    if (_collectionView) {
+        [self _registerCellClassForReuseID:templateType];
+    }
+}
+
+- (WXCellSlotComponent *)dequeueCellSlotWithType:(NSString *)type 
forIndexPath:(NSIndexPath *)indexPath
+{
+    WXAssertMainThread();
+    
+    WXCellSlotComponent *cellSlot = [_templateTypeMap objectForKey:type];
+    return [cellSlot copy];
+}
+
+- (WXCellSlotComponent *)templateWithType:(NSString *)type
+{
+    return [_templateTypeMap objectForKey:type];;
+}
+
+- (void)_registerCellClassForReuseID:(NSString *)templateID
+{
+    WXLogDebug(@"register cell class for template id:%@", templateID);
+    //TODO: register class updateTemplateId
+    [_collectionView registerClass:[WXReusableCollectionViewCell class] 
forCellWithReuseIdentifier:templateID];
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.h
----------------------------------------------------------------------
diff --git 
a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.h 
b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.h
new file mode 100644
index 0000000..c96bbcd
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Foundation/Foundation.h>
+
+@interface WXRecycleListUpdateManager : NSObject
+
+@property (nonatomic, weak) UICollectionView *collectionView;
+
+- (void)reload;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.m
----------------------------------------------------------------------
diff --git 
a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.m 
b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.m
new file mode 100644
index 0000000..1395607
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.m
@@ -0,0 +1,29 @@
+/*
+ * 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 "WXRecycleListUpdateManager.h"
+
+@implementation WXRecycleListUpdateManager
+
+- (void)reload
+{
+    [_collectionView reloadData];
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/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 e579139..0902eab 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.m
@@ -100,7 +100,7 @@
 
 - (void)_moveToSupercomponent:(WXComponent *)newSupercomponent 
atIndex:(NSUInteger)index
 {
-    if (self.delegate == newSupercomponent) {
+    if (self.delegate == (id<WXCellRenderDelegate>)newSupercomponent) {
         [self.delegate cell:self didMoveToIndex:index];
         [super _removeFromSupercomponent];
         [newSupercomponent _insertSubcomponent:self atIndex:index];

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h 
b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
index 1452118..1b0f784 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
+++ b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h
@@ -25,6 +25,7 @@
 @class WXTouchGestureRecognizer;
 @class WXThreadSafeCounter;
 
+typedef id (^WXDataBindingBlock)(NSDictionary *data, BOOL *needUpdate);
 
 /**
  * The following variables and methods are used in Weex INTERNAL logic.
@@ -131,6 +132,21 @@
     BOOL _lazyCreateView;
     
     WXTransform *_transform;
+    
+    /**
+     * Data Binding
+     */
+    BOOL _isTemplate;
+    WXComponent *_templateComponent;
+    WXDataBindingBlock _bindingMatch;
+    WXDataBindingBlock _bindingRepeat;
+    NSString *_repeatIndexIdentify;
+    NSString *_repeatLabelIdentify;
+    BOOL _isRepeating;
+    BOOL _isSkipUpdate;
+    
+    NSMutableDictionary<NSString *, NSArray<NSString *> *> *_bindingAttributes;
+    NSMutableDictionary<NSString *, NSArray<NSString *> *> *_bindingStyles;
 }
 
 ///--------------------------------------
@@ -226,6 +242,10 @@
 
 - (void)setGradientLayer;
 
+- (void)_storeBindingsWithStyles:(NSDictionary *)styles 
attributes:(NSDictionary *)attributes;
+
+- (void)_didInserted;
+
 @end
 
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m 
b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m
index c2db44a..ef1c73d 100644
--- a/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m
+++ b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m
@@ -109,6 +109,10 @@
     [self registerComponent:@"textarea" 
withClass:NSClassFromString(@"WXTextAreaComponent")];
        [self registerComponent:@"canvas" 
withClass:NSClassFromString(@"WXCanvasComponent")];
     [self registerComponent:@"slider-neighbor" 
withClass:NSClassFromString(@"WXSliderNeighborComponent")];
+    
+    [self registerComponent:@"recycle-list" 
withClass:NSClassFromString(@"WXRecycleListComponent")];
+    [self registerComponent:@"cell-slot" 
withClass:NSClassFromString(@"WXCellSlotComponent") withProperties: 
@{@"append":@"tree", @"isTemplate":@YES}];
+    
 }
 
 + (void)registerComponent:(NSString *)name withClass:(Class)clazz

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.h 
b/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.h
index f2d2f6a..73b08e1 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.h
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.h
@@ -18,6 +18,16 @@
  */
 
 #import <Foundation/Foundation.h>
+#import "WXInvocationConfig.h"
+
+@interface WXComponentConfig : WXInvocationConfig
+
+@property (nonatomic, strong) NSDictionary *properties;
+
+- (instancetype)initWithName:(NSString *)name class:(NSString *)clazz 
pros:(NSDictionary *)pros;
+
+@end
+
 
 @interface WXComponentFactory : NSObject
 
@@ -53,6 +63,8 @@
  */
 + (Class)classWithComponentName:(NSString *)name;
 
++ (WXComponentConfig *)configWithComponentName:(NSString *)name;
+
 /**
  * @abstract Returns the registered components.
  */

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.m 
b/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.m
index 6970376..0101d7a 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.m
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.m
@@ -20,17 +20,9 @@
 #import "WXComponentFactory.h"
 #import "WXAssert.h"
 #import "WXLog.h"
-#import "WXInvocationConfig.h"
 
 #import <objc/runtime.h>
 
-@interface WXComponentConfig : WXInvocationConfig
-@property (nonatomic, strong) NSDictionary *properties;
-
-- (instancetype)initWithName:(NSString *)name class:(NSString *)clazz 
pros:(NSDictionary *)pros;
-
-@end
-
 @implementation WXComponentConfig
 
 - (instancetype)initWithName:(NSString *)name class:(NSString *)clazz 
pros:(NSDictionary *)pros
@@ -82,7 +74,17 @@
 
 + (Class)classWithComponentName:(NSString *)name
 {
-    return [[self sharedInstance] classWithComponentName:name];
+    WXComponentConfig *config = [self configWithComponentName:name];
+    if(!config || !config.clazz) {
+        return nil;
+    }
+    
+    return NSClassFromString(config.clazz);
+}
+
++ (WXComponentConfig *)configWithComponentName:(NSString *)name
+{
+    return [[self sharedInstance] configWithComponentName:name];
 }
 
 + (void)registerComponent:(NSString *)name withClass:(Class)clazz 
withPros:(NSDictionary *)pros
@@ -195,9 +197,9 @@
     return componentDic;
 }
 
-- (Class)classWithComponentName:(NSString *)name
+- (WXComponentConfig *)configWithComponentName:(NSString *)name
 {
-    WXAssert(name, @"Can not find class for a nil component name");
+    WXAssert(name, @"Can not find config for a nil component name");
     
     WXComponentConfig *config = nil;
     
@@ -209,11 +211,7 @@
     }
     [_configLock unlock];
     
-    if(!config || !config.clazz) {
-        return nil;
-    }
-    
-    return NSClassFromString(config.clazz);
+    return config;
 }
 
 - (void)registerComponent:(NSString *)name withClass:(Class)clazz 
withPros:(NSDictionary *)pros

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h 
b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h
index 729e6d7..387e3d0 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h
@@ -24,8 +24,15 @@
 @class WXSDKInstance;
 @class WXComponent;
 
-extern void WXPerformBlockOnComponentThread(void (^block)());
-
+#ifdef __cplusplus
+extern "C" {
+#endif
+    
+void WXPerformBlockOnComponentThread(void (^block)());
+    
+#ifdef __cplusplus
+}
+#endif
 
 @interface WXComponentManager : NSObject
 
@@ -91,6 +98,7 @@ extern void WXPerformBlockOnComponentThread(void (^block)());
  */
 - (NSUInteger)numberOfComponents;
 
+- (void)addComponent:(WXComponent *)component toIndexDictForRef:(NSString 
*)ref;
 
 ///--------------------------------------
 /// @name Updating

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m 
b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m
index 86ec447..bfd96eb 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m
@@ -20,6 +20,7 @@
 #import "WXComponentManager.h"
 #import "WXComponent.h"
 #import "WXComponent_internal.h"
+#import "WXComponent+DataBinding.h"
 #import "WXComponentFactory.h"
 #import "WXDefine.h"
 #import "NSArray+Weex.h"
@@ -204,6 +205,15 @@ static NSThread *WXComponentThread;
     _rootComponent = [self _buildComponentForData:data supercomponent:nil];
     
     [self _initRootCSSNode];
+    
+    NSArray *subcomponentsData = [data valueForKey:@"children"];
+    if (subcomponentsData) {
+        BOOL appendTree = [_rootComponent.attributes[@"append"] 
isEqualToString:@"tree"];
+        for(NSDictionary *subcomponentData in subcomponentsData){
+            [self _recursivelyAddComponent:subcomponentData 
toSupercomponent:_rootComponent atIndex:-1 appendingInTree:appendTree];
+        }
+    }
+    
     __weak typeof(self) weakSelf = self;
     [self _addUITask:^{
         [WXTracingManager 
startTracingWithInstanceId:weakSelf.weexInstance.instanceId ref:data[@"ref"] 
className:nil name:data[@"type"] phase:WXTracingBegin 
functionName:@"createBody" options:@{@"threadName":WXTUIThread}];
@@ -212,6 +222,8 @@ static NSThread *WXComponentThread;
         [strongSelf.weexInstance.rootView 
addSubview:strongSelf->_rootComponent.view];
         [WXTracingManager 
startTracingWithInstanceId:weakSelf.weexInstance.instanceId ref:data[@"ref"] 
className:nil name:data[@"type"] phase:WXTracingEnd functionName:@"createBody" 
options:@{@"threadName":WXTUIThread}];
     }];
+    
+    
 }
 
 static bool rootNodeIsDirty(void *context)
@@ -258,14 +270,16 @@ static css_node_t * rootNodeGetChild(void *context, int i)
     if(supercomponent && component && supercomponent->_lazyCreateView) {
         component->_lazyCreateView = YES;
     }
-
-    __weak typeof(self) weakSelf = self;
-    [self _addUITask:^{
-        [WXTracingManager 
startTracingWithInstanceId:weakSelf.weexInstance.instanceId 
ref:componentData[@"ref"] className:nil name:componentData[@"type"] 
phase:WXTracingBegin functionName:@"addElement" 
options:@{@"threadName":WXTUIThread}];
-        [supercomponent insertSubview:component atIndex:index];
-        [WXTracingManager 
startTracingWithInstanceId:weakSelf.weexInstance.instanceId 
ref:componentData[@"ref"] className:nil name:componentData[@"type"] 
phase:WXTracingEnd functionName:@"addElement" 
options:@{@"threadName":WXTUIThread}];
-    }];
-
+    
+    if (!component->_isTemplate) {
+        __weak typeof(self) weakSelf = self;
+        [self _addUITask:^{
+            [WXTracingManager 
startTracingWithInstanceId:weakSelf.weexInstance.instanceId 
ref:componentData[@"ref"] className:nil name:componentData[@"type"] 
phase:WXTracingBegin functionName:@"addElement" 
options:@{@"threadName":WXTUIThread}];
+            [supercomponent insertSubview:component atIndex:index];
+            [WXTracingManager 
startTracingWithInstanceId:weakSelf.weexInstance.instanceId 
ref:componentData[@"ref"] className:nil name:componentData[@"type"] 
phase:WXTracingEnd functionName:@"addElement" 
options:@{@"threadName":WXTUIThread}];
+        }];
+    }
+    
     NSArray *subcomponentsData = [componentData valueForKey:@"children"];
     
     BOOL appendTree = !appendingInTree && [component.attributes[@"append"] 
isEqualToString:@"tree"];
@@ -273,6 +287,9 @@ static css_node_t * rootNodeGetChild(void *context, int i)
     for(NSDictionary *subcomponentData in subcomponentsData){
         [self _recursivelyAddComponent:subcomponentData 
toSupercomponent:component atIndex:-1 appendingInTree:appendTree || 
appendingInTree];
     }
+    
+    [component _didInserted];
+    
     if (appendTree) {
         // If appending tree,force layout in case of too much tasks piling 
up in syncQueue
         [self _layoutAndSyncUI];
@@ -383,9 +400,26 @@ static css_node_t * rootNodeGetChild(void *context, int i)
             }
         }
     }
-
-    Class clazz = [WXComponentFactory classWithComponentName:type];
+    
+    WXComponentConfig *config = [WXComponentFactory 
configWithComponentName:type];
+    BOOL isTemplate = [config.properties[@"isTemplate"] boolValue] || 
(supercomponent && supercomponent->_isTemplate);
+    NSDictionary *bindingStyles;
+    NSDictionary *bindingAttibutes;
+    NSDictionary *bindingEvents;
+    if (isTemplate) {
+        bindingStyles = [self _extractBindings:&styles];
+        bindingAttibutes = [self _extractBindings:&attributes];
+        bindingEvents = [self _extractBindingEvents:&events];
+    }
+    
+    Class clazz = NSClassFromString(config.clazz);;
     WXComponent *component = [[clazz alloc] initWithRef:ref type:type 
styles:styles attributes:attributes events:events 
weexInstance:self.weexInstance];
+    
+    if (isTemplate) {
+        component->_isTemplate = YES;
+        [component _storeBindingsWithStyles:bindingStyles 
attributes:bindingAttibutes];
+    }
+
     WXAssert(component, @"Component build failed for data:%@", data);
     
     [_indexDict setObject:component forKey:component.ref];
@@ -393,6 +427,67 @@ static css_node_t * rootNodeGetChild(void *context, int i)
     return component;
 }
 
+- (void)addComponent:(WXComponent *)component toIndexDictForRef:(NSString *)ref
+{
+    [_indexDict setObject:component forKey:ref];
+}
+
+- (NSDictionary *)_extractBindings:(NSDictionary **)attributesOrStylesPoint
+{
+    NSDictionary *attributesOrStyles = *attributesOrStylesPoint;
+    if (!attributesOrStyles) {
+        return nil;
+    }
+    
+    NSMutableDictionary *newAttributesOrStyles = [attributesOrStyles 
mutableCopy];
+    NSMutableDictionary *bindingAttributesOrStyles = [NSMutableDictionary 
dictionary];
+    
+    [attributesOrStyles enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull 
attributeOrStyleName, id  _Nonnull attributeOrStyle, BOOL * _Nonnull stop) {
+        if ([WXBindingMatchIdentify isEqualToString:attributeOrStyleName] // 
match
+            ||  [WXBindingRepeatIdentify isEqualToString:attributeOrStyleName] 
// repeat
+            || ([attributeOrStyle isKindOfClass:[NSDictionary class]] && 
attributeOrStyle[WXBindingIdentify])) {  // {"attributeOrStyleName": 
{"@binding":"bindingExpression"}
+            bindingAttributesOrStyles[attributeOrStyleName] = attributeOrStyle;
+            [newAttributesOrStyles removeObjectForKey:attributeOrStyleName];
+        } else if ([attributeOrStyle isKindOfClass:[NSArray class]]) {
+            // {"attributeOrStyleName":[..., "string", 
{"@binding":"bindingExpression"}, "string", {"@binding":"bindingExpression"}, 
...]
+            __block BOOL isBinding = NO;
+            [attributeOrStyle enumerateObjectsUsingBlock:^(id  _Nonnull obj, 
NSUInteger idx, BOOL * _Nonnull stop) {
+                if ([obj isKindOfClass:[NSDictionary class]] && 
obj[WXBindingIdentify]) {
+                    isBinding = YES;
+                    *stop = YES;
+                }
+            }];
+            
+            if (isBinding) {
+                bindingAttributesOrStyles[attributeOrStyleName] = 
attributeOrStyle;
+                [newAttributesOrStyles 
removeObjectForKey:attributeOrStyleName];
+            }
+        }
+    }];
+    
+    *attributesOrStylesPoint = newAttributesOrStyles;
+    
+    return bindingAttributesOrStyles;
+}
+
+- (NSDictionary *)_extractBindingEvents:(NSArray **)eventsPoint
+{
+    NSArray *events = *eventsPoint;
+    NSMutableArray *newEvents = [events mutableCopy];
+    NSMutableDictionary *bindingEvents = [NSMutableDictionary dictionary];
+    [events enumerateObjectsUsingBlock:^(id  _Nonnull event, NSUInteger idx, 
BOOL * _Nonnull stop) {
+        if ([event isKindOfClass:[NSDictionary class]] && event[@"type"] && 
event[@"params"]) {
+            NSString *eventName = event[@"type"];
+            NSString *bindingParams = event[@"params"];
+            bindingEvents[eventName] = bindingParams;
+            [newEvents removeObject:event];
+        }
+    }];
+    
+    *eventsPoint = newEvents;
+    return bindingEvents;
+}
+
 #pragma mark Reset
 -(BOOL)isShouldReset:(id )value
 {

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Model/WXComponent.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXComponent.h 
b/ios/sdk/WeexSDK/Sources/Model/WXComponent.h
index 39385ef..ac1b13a 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXComponent.h
+++ b/ios/sdk/WeexSDK/Sources/Model/WXComponent.h
@@ -23,6 +23,11 @@
 
 @class WXSDKInstance;
 
+typedef enum : NSUInteger {
+    WXDisplayTypeNone,
+    WXDisplayTypeBlock
+} WXDisplayType;
+
 /**
  * @abstract the component callback , result can be string or dictionary.
  * @discussion callback data to js, the id of callback function will be 
removed to save memory.
@@ -37,7 +42,7 @@ typedef void (^WXKeepAliveCallback)(_Nonnull id result, BOOL 
keepAlive);
 
 NS_ASSUME_NONNULL_BEGIN
 
-@interface WXComponent : NSObject
+@interface WXComponent : NSObject <NSCopying>
 
 ///--------------------------------------
 /// @name Component Hierarchy Management
@@ -346,6 +351,8 @@ NS_ASSUME_NONNULL_BEGIN
 /// @name Display
 ///--------------------------------------
 
+@property (nonatomic, assign) WXDisplayType displayType;
+
 /**
  * @abstract Marks the view as needing display. The method should be called on 
the main thread.
  * @discussion You can use this method to notify the system that your 
component's contents need to be redrawn. This method makes a note of the 
request and returns immediately. The component is not actually redrawn until 
the next drawing cycle, at which point all invalidated components are updated.
@@ -399,6 +406,16 @@ NS_ASSUME_NONNULL_BEGIN
  */
 - (UIImage *)endDrawContext:(CGContextRef)context;
 
+///--------------------------------------
+/// @name Data Binding
+///--------------------------------------
+
+/**
+ * @abstract Update binding data for the component
+ * @parameter binding data to update
+ */
+- (void)updateBindingData:(NSDictionary *)data;
+
 @end
 
 @interface WXComponent (Deprecated)

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/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 81f8178..76fb446 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m
@@ -88,6 +88,7 @@
         
         _absolutePosition = CGPointMake(NAN, NAN);
         
+        _displayType = WXDisplayTypeBlock;
         _isNeedJoinLayoutSystem = YES;
         _isLayoutDirty = YES;
         _isViewFrameSyncWithCalculated = YES;
@@ -136,6 +137,41 @@
     return self;
 }
 
+- (id)copyWithZone:(NSZone *)zone
+{
+    NSInteger copyId = 0;
+    @synchronized(self){
+        static NSInteger __copy = 0;
+        copyId = __copy % (1024*1024);
+        __copy++;
+    }
+    NSString *copyRef = [NSString stringWithFormat:@"%ldcopy_of%@", copyId, 
_isTemplate ? self.ref : self->_templateComponent.ref];
+    WXComponent *component = [[[self class] allocWithZone:zone] 
initWithRef:copyRef type:self.type styles:self.styles 
attributes:self.attributes events:self.events weexInstance:self.weexInstance];
+    if (_isTemplate) {
+        component->_templateComponent = self;
+    } else {
+        component->_templateComponent = self->_templateComponent;
+    }
+    memcpy(component->_cssNode, self.cssNode, sizeof(css_node_t));
+    component->_cssNode->context = (__bridge void *)component;
+    component->_calculatedFrame = self.calculatedFrame;
+    
+    NSMutableArray *subcomponentsCopy = [NSMutableArray array];
+    for (WXComponent *subcomponent in self.subcomponents) {
+        WXComponent *subcomponentCopy = [subcomponent copy];
+        subcomponentCopy->_supercomponent = component;
+        [subcomponentsCopy addObject:subcomponentCopy];
+    }
+    
+    component->_subcomponents = subcomponentsCopy;
+    
+    WXPerformBlockOnComponentThread(^{
+        [self.weexInstance.componentManager addComponent:component 
toIndexDictForRef:copyRef];
+    });
+    
+    return component;
+}
+
 - (void)dealloc
 {
     free_css_node(_cssNode);
@@ -195,6 +231,28 @@
     return events;
 }
 
+- (void)setDisplayType:(WXDisplayType)displayType
+{
+    if (_displayType != displayType) {
+        _displayType = displayType;
+        if (displayType == WXDisplayTypeNone) {
+            _isNeedJoinLayoutSystem = NO;
+            [self.supercomponent _recomputeCSSNodeChildren];
+            WXPerformBlockOnMainThread(^{
+                [self removeFromSuperview];
+            });
+        } else {
+            _isNeedJoinLayoutSystem = YES;
+            [self.supercomponent _recomputeCSSNodeChildren];
+            WXPerformBlockOnMainThread(^{
+                [self _buildViewHierarchyLazily];
+                // TODO: insert into the correct index
+                [self.supercomponent insertSubview:self atIndex:0];
+            });
+        }
+    }
+}
+
 - (WXSDKInstance *)weexInstance
 {
     return _weexInstance;
@@ -423,6 +481,11 @@
     [newSupercomponent _insertSubcomponent:self atIndex:index];
 }
 
+- (void)_didInserted
+{
+    
+}
+
 - (id<WXScrollerProtocol>)ancestorScroller
 {
     if(!_ancestorScroller) {

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/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 9396243..4b05df3 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXDiffUtil.m
@@ -107,7 +107,9 @@ typedef enum : NSUInteger {
         }
     }
     
+#if DEBUG
     [self _printMatrix:matrix rowSize:oldSize columnSize:newSize];
+#endif
     
     NSMutableArray *updates = [NSMutableArray array];
     NSMutableIndexSet *inserts = [NSMutableIndexSet indexSet];

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h 
b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h
index 5d96757..538dc77 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h
@@ -81,33 +81,41 @@ do {\
     }\
 }while(0)
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+    
 /**
  * @abstract execute asynchronous action block on the main thread.
  *
  */
-extern void WXPerformBlockOnMainThread( void (^ _Nonnull block)());
+void WXPerformBlockOnMainThread( void (^ _Nonnull block)());
 
 /**
  * @abstract execute synchronous action block on the main thread.
  *
  */
-extern void WXPerformBlockSyncOnMainThread( void (^ _Nonnull block)());
+void WXPerformBlockSyncOnMainThread( void (^ _Nonnull block)());
 
 /**
  * @abstract execute action block on the specific thread.
  *
  */
-extern void WXPerformBlockOnThread(void (^ _Nonnull block)(), NSThread 
*_Nonnull thread);
+void WXPerformBlockOnThread(void (^ _Nonnull block)(), NSThread *_Nonnull 
thread);
 
 /**
  * @abstract swizzling methods.
  *
  */
-extern void WXSwizzleInstanceMethod(_Nonnull Class className, _Nonnull SEL 
original, _Nonnull SEL replaced);
+void WXSwizzleInstanceMethod(_Nonnull Class className, _Nonnull SEL original, 
_Nonnull SEL replaced);
 
-extern void WXSwizzleInstanceMethodWithBlock(_Nonnull Class className, 
_Nonnull SEL original, _Nonnull id block, _Nonnull SEL replaced);
+void WXSwizzleInstanceMethodWithBlock(_Nonnull Class className, _Nonnull SEL 
original, _Nonnull id block, _Nonnull SEL replaced);
 
-extern _Nonnull SEL WXSwizzledSelectorForSelector(_Nonnull SEL selector);
+_Nonnull SEL WXSwizzledSelectorForSelector(_Nonnull SEL selector);
+    
+#ifdef __cplusplus
+}
+#endif
 
 @interface WXUtility : NSObject
 

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/877487a6/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.m 
b/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.m
index ef00f9a..be27ae7 100644
--- a/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.m
+++ b/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.m
@@ -94,6 +94,10 @@ do {\
 {
     WXAssertMainThread();
     
+    if (subcomponent.displayType == WXDisplayTypeNone) {
+        return;
+    }
+    
     WX_CHECK_COMPONENT_TYPE(self.componentType)
     if (subcomponent->_positionType == WXPositionTypeFixed) {
         [self.weexInstance.rootView addSubview:subcomponent.view];

Reply via email to