weex-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jinji...@apache.org
Subject [14/50] [abbrv] incubator-weex git commit: + [ios] iOS init.
Date Tue, 24 Jan 2017 08:18:29 GMT
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Layout/Layout.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Layout/Layout.h b/ios/sdk/WeexSDK/Sources/Layout/Layout.h
new file mode 100644
index 0000000..1df5822
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Layout/Layout.h
@@ -0,0 +1,177 @@
+/**
+ * Copyright (c) 2014, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+#ifndef __LAYOUT_H
+#define __LAYOUT_H
+
+#include <math.h>
+#ifndef __cplusplus
+#include <stdbool.h>
+#endif
+
+// Not defined in MSVC++
+#ifndef NAN
+static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff};
+#define NAN (*(const float *)__nan)
+#endif
+
+#define CSS_UNDEFINED NAN
+
+typedef enum {
+  CSS_DIRECTION_INHERIT = 0,
+  CSS_DIRECTION_LTR,
+  CSS_DIRECTION_RTL
+} css_direction_t;
+
+typedef enum {
+  CSS_FLEX_DIRECTION_COLUMN = 0,
+  CSS_FLEX_DIRECTION_COLUMN_REVERSE,
+  CSS_FLEX_DIRECTION_ROW,
+  CSS_FLEX_DIRECTION_ROW_REVERSE
+} css_flex_direction_t;
+
+typedef enum {
+  CSS_JUSTIFY_FLEX_START = 0,
+  CSS_JUSTIFY_CENTER,
+  CSS_JUSTIFY_FLEX_END,
+  CSS_JUSTIFY_SPACE_BETWEEN,
+  CSS_JUSTIFY_SPACE_AROUND
+} css_justify_t;
+
+// Note: auto is only a valid value for alignSelf. It is NOT a valid value for
+// alignItems.
+typedef enum {
+  CSS_ALIGN_AUTO = 0,
+  CSS_ALIGN_FLEX_START,
+  CSS_ALIGN_CENTER,
+  CSS_ALIGN_FLEX_END,
+  CSS_ALIGN_STRETCH
+} css_align_t;
+
+typedef enum {
+  CSS_POSITION_RELATIVE = 0,
+  CSS_POSITION_ABSOLUTE
+} css_position_type_t;
+
+typedef enum {
+  CSS_NOWRAP = 0,
+  CSS_WRAP
+} css_wrap_type_t;
+
+// Note: left and top are shared between position[2] and position[4], so
+// they have to be before right and bottom.
+typedef enum {
+  CSS_LEFT = 0,
+  CSS_TOP,
+  CSS_RIGHT,
+  CSS_BOTTOM,
+  CSS_START,
+  CSS_END,
+  CSS_POSITION_COUNT
+} css_position_t;
+
+typedef enum {
+  CSS_MEASURE_MODE_UNDEFINED = 0,
+  CSS_MEASURE_MODE_EXACTLY,
+  CSS_MEASURE_MODE_AT_MOST
+} css_measure_mode_t;
+
+typedef enum {
+  CSS_WIDTH = 0,
+  CSS_HEIGHT
+} css_dimension_t;
+
+typedef struct {
+  float position[4];
+  float dimensions[2];
+  css_direction_t direction;
+
+  // Instead of recomputing the entire layout every single time, we
+  // cache some information to break early when nothing changed
+  bool should_update;
+  float last_requested_dimensions[2];
+  float last_parent_max_width;
+  float last_parent_max_height;
+  float last_dimensions[2];
+  float last_position[2];
+  css_direction_t last_direction;
+} css_layout_t;
+
+typedef struct {
+  float dimensions[2];
+} css_dim_t;
+
+typedef struct {
+  css_direction_t direction;
+  css_flex_direction_t flex_direction;
+  css_justify_t justify_content;
+  css_align_t align_content;
+  css_align_t align_items;
+  css_align_t align_self;
+  css_position_type_t position_type;
+  css_wrap_type_t flex_wrap;
+  float flex;
+  float margin[6];
+  float position[4];
+  /**
+   * You should skip all the rules that contain negative values for the
+   * following attributes. For example:
+   *   {padding: 10, paddingLeft: -5}
+   * should output:
+   *   {left: 10 ...}
+   * the following two are incorrect:
+   *   {left: -5 ...}
+   *   {left: 0 ...}
+   */
+  float padding[6];
+  float border[6];
+  float dimensions[2];
+  float minDimensions[2];
+  float maxDimensions[2];
+} css_style_t;
+
+typedef struct css_node css_node_t;
+struct css_node {
+  css_style_t style;
+  css_layout_t layout;
+  int children_count;
+  int line_index;
+
+  css_node_t *next_absolute_child;
+  css_node_t *next_flex_child;
+
+  css_dim_t (*measure)(void *context, float width, css_measure_mode_t widthMode, float height, css_measure_mode_t heightMode);
+  void (*print)(void *context);
+  struct css_node* (*get_child)(void *context, int i);
+  bool (*is_dirty)(void *context);
+  void *context;
+};
+
+// Lifecycle of nodes and children
+css_node_t *new_css_node(void);
+void init_css_node(css_node_t *node);
+void free_css_node(css_node_t *node);
+
+// Print utilities
+typedef enum {
+  CSS_PRINT_LAYOUT = 1,
+  CSS_PRINT_STYLE = 2,
+  CSS_PRINT_CHILDREN = 4,
+} css_print_options_t;
+void print_css_node(css_node_t *node, css_print_options_t options);
+
+bool isUndefined(float value);
+
+// Function that computes the layout!
+void layoutNode(css_node_t *node, float maxWidth, float maxHeight, css_direction_t parentDirection);
+
+// Reset the calculated layout values for a given node. You should call this before `layoutNode`.
+void resetNodeLayout(css_node_t *node);
+
+#endif

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.h b/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.h
new file mode 100644
index 0000000..d8e7b6f
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.h
@@ -0,0 +1,13 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+#import <WeexSDK/WeexSDK.h>
+
+@interface WXComponent (Layout)
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.m b/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.m
new file mode 100644
index 0000000..68b5edc
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.m
@@ -0,0 +1,296 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+#import "WXComponent+Layout.h"
+#import "WXComponent_internal.h"
+#import "WXTransform.h"
+#import "WXAssert.h"
+
+@implementation WXComponent (Layout)
+
+#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
+
+#pragma mark Public
+
+- (CGRect)calculatedFrame
+{
+    return _calculatedFrame;
+}
+
+- (CGPoint)absolutePosition
+{
+    return _absolutePosition;
+}
+
+- (css_node_t *)cssNode
+{
+    return _cssNode;
+}
+
+- (void)setNeedsLayout
+{
+    _isLayoutDirty = YES;
+    WXComponent *supercomponent = [self supercomponent];
+    if(supercomponent){
+        [supercomponent setNeedsLayout];
+    }
+}
+
+- (BOOL)needsLayout
+{
+    return _isLayoutDirty;
+}
+
+- (CGSize (^)(CGSize))measureBlock
+{
+    return nil;
+}
+
+- (void)layoutDidFinish
+{
+    WXAssertMainThread();
+}
+
+#pragma mark Private
+
+- (void)_initCSSNodeWithStyles:(NSDictionary *)styles
+{
+    _cssNode = new_css_node();
+    
+    _cssNode->print = cssNodePrint;
+    _cssNode->get_child = cssNodeGetChild;
+    _cssNode->is_dirty = cssNodeIsDirty;
+    if ([self measureBlock]) {
+        _cssNode->measure = cssNodeMeasure;
+    }
+    _cssNode->context = (__bridge void *)self;
+    
+    
+    
+    [self _recomputeCSSNodeChildren];
+    [self _fillCSSNode:styles];
+    
+    // TODO: JS Default flex:1 on root, not here
+    if ([self.ref isEqualToString:WX_SDK_ROOT_REF] && isUndefined(_cssNode->style.dimensions[CSS_HEIGHT])) {
+        _cssNode->style.flex = 1.0;
+    }
+}
+
+- (void)_updateCSSNodeStyles:(NSDictionary *)styles
+{
+    [self _fillCSSNode:styles];
+}
+
+- (void)_recomputeCSSNodeChildren
+{
+    _cssNode->children_count = (int)[self _childrenCountForLayout];
+}
+
+- (NSUInteger)_childrenCountForLayout
+{
+    NSUInteger count = self.subcomponents.count;
+    for (WXComponent *component in self.subcomponents) {
+        if (!component->_isNeedJoinLayoutSystem) {
+            count--;
+        }
+    }
+    return (int)(count);
+}
+
+- (void)_calculatedFrameDidChange
+{
+    WXAssertComponentThread();
+}
+
+- (void)_calculateFrameWithSuperAbsolutePosition:(CGPoint)superAbsolutePosition
+                           gatherDirtyComponents:(NSMutableSet<WXComponent *> *)dirtyComponents
+{
+    WXAssertComponentThread();
+    
+    if (!_cssNode->layout.should_update) {
+        return;
+    }
+    _cssNode->layout.should_update = false;
+    _isLayoutDirty = NO;
+    
+    CGRect newFrame = CGRectMake(WXRoundPixelValue(_cssNode->layout.position[CSS_LEFT]),
+                                 WXRoundPixelValue(_cssNode->layout.position[CSS_TOP]),
+                                 WXRoundPixelValue(_cssNode->layout.dimensions[CSS_WIDTH]),
+                                 WXRoundPixelValue(_cssNode->layout.dimensions[CSS_HEIGHT]));
+    
+    if (!CGRectEqualToRect(newFrame, _calculatedFrame)) {
+        _calculatedFrame = newFrame;
+        [self _recomputeBorderRadius];
+        [self _calculatedFrameDidChange];
+        [dirtyComponents addObject:self];
+    }
+    
+    CGPoint newAboslutePosition = CGPointMake(WXRoundPixelValue(superAbsolutePosition.x + _cssNode->layout.position[CSS_LEFT]),
+                                              WXRoundPixelValue(superAbsolutePosition.y + _cssNode->layout.position[CSS_TOP]));
+    
+    if(!CGPointEqualToPoint(_absolutePosition, newAboslutePosition)){
+        _absolutePosition = newAboslutePosition;
+    }
+    
+    _cssNode->layout.dimensions[CSS_WIDTH] = CSS_UNDEFINED;
+    _cssNode->layout.dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
+    _cssNode->layout.position[CSS_LEFT] = 0;
+    _cssNode->layout.position[CSS_TOP] = 0;
+    
+    for (WXComponent *subcomponent in self.subcomponents) {
+        [subcomponent _calculateFrameWithSuperAbsolutePosition:newAboslutePosition gatherDirtyComponents:dirtyComponents];
+    }
+}
+
+- (void)_layoutDidFinish
+{
+    WXAssertMainThread();
+    
+    if ([self isViewLoaded] && !CGRectEqualToRect(_calculatedFrame, self.view.frame)) {
+        self.view.frame = _calculatedFrame;
+        // transform does not belong to layout, move it to other place hopefully
+        if (_transform) {
+            _layer.transform = [[WXTransform new] getTransform:_transform withView:self.view withOrigin:_transformOrigin];
+        }
+        [_layer setNeedsDisplay];
+    }
+    
+    if (_positionType == WXPositionTypeSticky) {
+        [self.ancestorScroller adjustSticky];
+    }
+    
+    [self layoutDidFinish];
+}
+
+#define WX_STYLE_FILL_CSS_NODE(key, cssProp, type)\
+do {\
+    id value = styles[@#key];\
+    if (value) {\
+        _cssNode->style.cssProp = (typeof(_cssNode->style.cssProp))[WXConvert type:value];\
+        [self setNeedsLayout];\
+    }\
+} while(0);
+
+#define WX_STYLE_FILL_CSS_NODE_ALL_DIRECTION(key, cssProp, type) \
+do {\
+    WX_STYLE_FILL_CSS_NODE(key, cssProp[CSS_TOP], type)\
+    WX_STYLE_FILL_CSS_NODE(key, cssProp[CSS_LEFT], type)\
+    WX_STYLE_FILL_CSS_NODE(key, cssProp[CSS_RIGHT], type)\
+    WX_STYLE_FILL_CSS_NODE(key, cssProp[CSS_BOTTOM], type)\
+} while(0);
+
+- (void)_fillCSSNode:(NSDictionary *)styles;
+{
+    // flex
+    WX_STYLE_FILL_CSS_NODE(flex, flex, CGFloat)
+    WX_STYLE_FILL_CSS_NODE(flexDirection, flex_direction, css_flex_direction_t)
+    WX_STYLE_FILL_CSS_NODE(alignItems, align_items, css_align_t)
+    WX_STYLE_FILL_CSS_NODE(alignSelf, align_self, css_align_t)
+    WX_STYLE_FILL_CSS_NODE(flexWrap, flex_wrap, css_wrap_type_t)
+    WX_STYLE_FILL_CSS_NODE(justifyContent, justify_content, css_justify_t)
+    
+    // position
+    WX_STYLE_FILL_CSS_NODE(position, position_type, css_position_type_t)
+    WX_STYLE_FILL_CSS_NODE(top, position[CSS_TOP], WXPixelType)
+    WX_STYLE_FILL_CSS_NODE(left, position[CSS_LEFT], WXPixelType)
+    WX_STYLE_FILL_CSS_NODE(right, position[CSS_RIGHT], WXPixelType)
+    WX_STYLE_FILL_CSS_NODE(bottom, position[CSS_BOTTOM], WXPixelType)
+    
+    // dimension
+    WX_STYLE_FILL_CSS_NODE(width, dimensions[CSS_WIDTH], WXPixelType)
+    WX_STYLE_FILL_CSS_NODE(height, dimensions[CSS_HEIGHT], WXPixelType)
+    WX_STYLE_FILL_CSS_NODE(minWidth, minDimensions[CSS_WIDTH], WXPixelType)
+    WX_STYLE_FILL_CSS_NODE(minHeight, minDimensions[CSS_HEIGHT], WXPixelType)
+    WX_STYLE_FILL_CSS_NODE(maxWidth, maxDimensions[CSS_WIDTH], WXPixelType)
+    WX_STYLE_FILL_CSS_NODE(maxHeight, maxDimensions[CSS_HEIGHT], WXPixelType)
+    
+    // margin
+    WX_STYLE_FILL_CSS_NODE_ALL_DIRECTION(margin, margin, WXPixelType)
+    WX_STYLE_FILL_CSS_NODE(marginTop, margin[CSS_TOP], WXPixelType)
+    WX_STYLE_FILL_CSS_NODE(marginLeft, margin[CSS_LEFT], WXPixelType)
+    WX_STYLE_FILL_CSS_NODE(marginRight, margin[CSS_RIGHT], WXPixelType)
+    WX_STYLE_FILL_CSS_NODE(marginBottom, margin[CSS_BOTTOM], WXPixelType)
+    
+    // border
+    WX_STYLE_FILL_CSS_NODE_ALL_DIRECTION(borderWidth, border, WXPixelType)
+    WX_STYLE_FILL_CSS_NODE(borderTopWidth, border[CSS_TOP], WXPixelType)
+    WX_STYLE_FILL_CSS_NODE(borderLeftWidth, border[CSS_LEFT], WXPixelType)
+    WX_STYLE_FILL_CSS_NODE(borderRightWidth, border[CSS_RIGHT], WXPixelType)
+    WX_STYLE_FILL_CSS_NODE(borderBottomWidth, border[CSS_BOTTOM], WXPixelType)
+    
+    // padding
+    WX_STYLE_FILL_CSS_NODE_ALL_DIRECTION(padding, padding, WXPixelType)
+    WX_STYLE_FILL_CSS_NODE(paddingTop, padding[CSS_TOP], WXPixelType)
+    WX_STYLE_FILL_CSS_NODE(paddingLeft, padding[CSS_LEFT], WXPixelType)
+    WX_STYLE_FILL_CSS_NODE(paddingRight, padding[CSS_RIGHT], WXPixelType)
+    WX_STYLE_FILL_CSS_NODE(paddingBottom, padding[CSS_BOTTOM], WXPixelType)
+}
+
+- (void)_fillAbsolutePositions
+{
+    CGPoint absolutePostion = self.absolutePosition;
+    for (WXComponent *subcomponent in self.subcomponents) {
+        subcomponent.absolutePosition = CGPointMake(absolutePostion.x + subcomponent.calculatedFrame.origin.x, absolutePostion.y + subcomponent.calculatedFrame.origin.y);
+        [subcomponent _fillAbsolutePositions];
+    }
+}
+
+#pragma mark CSS Node Override
+
+static void cssNodePrint(void *context)
+{
+    WXComponent *component = (__bridge WXComponent *)context;
+    // TODO:
+    printf("%s:%s ", component.ref.UTF8String, component->_type.UTF8String);
+}
+
+static css_node_t * cssNodeGetChild(void *context, int i)
+{
+    WXComponent *component = (__bridge WXComponent *)context;
+    
+    for (int j = 0; j <= i && j < component.subcomponents.count; j++) {
+        WXComponent *child = component.subcomponents[j];
+        if (!child->_isNeedJoinLayoutSystem) {
+            i++;
+        }
+    }
+    
+    if(i >= 0 && i < component.subcomponents.count){
+        WXComponent *child = component.subcomponents[i];
+        return child->_cssNode;
+    }
+    
+    return NULL;
+}
+
+static bool cssNodeIsDirty(void *context)
+{
+    WXAssertComponentThread();
+    
+    WXComponent *component = (__bridge WXComponent *)context;
+    BOOL needsLayout = [component needsLayout];
+    
+    return needsLayout;
+}
+
+static css_dim_t cssNodeMeasure(void *context, float width, css_measure_mode_t widthMode, float height, css_measure_mode_t heightMode)
+{
+    WXComponent *component = (__bridge WXComponent *)context;
+    CGSize (^measureBlock)(CGSize) = [component measureBlock];
+    
+    if (!measureBlock) {
+        return (css_dim_t){NAN, NAN};
+    }
+    
+    CGSize constrainedSize = CGSizeMake(width, height);
+    CGSize resultSize = measureBlock(constrainedSize);
+    
+    return (css_dim_t){resultSize.width, resultSize.height};
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h
new file mode 100644
index 0000000..cf2d330
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h
@@ -0,0 +1,119 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+#import <Foundation/Foundation.h>
+#import "WXBridgeMethod.h"
+
+@interface WXBridgeManager : NSObject
+
+/**
+ *  Create Instance Method
+ *  @param instance  :   instance id
+ *  @param template  :   template data
+ *  @param options   :   parameters
+ *  @param data      :   external data
+ **/
+- (void)createInstance:(NSString *)instance
+              template:(NSString *)temp
+               options:(NSDictionary *)options
+                  data:(id)data;
+
+/**
+ *  Destroy Instance Method
+ *  @param instance  :   instance id
+ **/
+- (void)destroyInstance:(NSString *)instance;
+
+/**
+ *  Refresh Instance Method
+ *  @param instance  :   instance id
+ *  @param data      :   external data
+ **/
+- (void)refreshInstance:(NSString *)instance
+                   data:(id)data;
+
+- (void)unload;
+
+/**
+ *  Update Instacne State Method
+ *  @param instance  :   instance id
+ *  @param data      :   parameters
+ **/
+- (void)updateState:(NSString *)instance
+               data:(id)data;
+
+/**
+ *  Execute JSFramework Script
+ *  @param script    :   script code
+ **/
+- (void)executeJsFramework:(NSString *)script;
+
+/**
+ *  Execute JS Method
+ *  @param method    :   object of bridge method
+ **/
+- (void)executeJsMethod:(WXBridgeMethod *)method;
+
+/**
+ *  Register Modules Method
+ *  @param modules   :   module list
+ **/
+- (void)registerModules:(NSDictionary *)modules;
+
+/**
+ *  Register Components Method
+ *  @param components:   component list
+ **/
+- (void)registerComponents:(NSArray* )components;
+
+/**
+ *  FireEvent
+ *  @param instanceId:   instance id
+ *  @param ref       :   node reference
+ *  @param type      :   event type
+ *  @param params    :   parameters
+ **/
+- (void)fireEvent:(NSString *)instanceId ref:(NSString *)ref type:(NSString *)type params:(NSDictionary *)params;
+
+/**
+ *  callBack
+ *
+ *  @param instanceId instanceId
+ *  @param funcId     funcId
+ *  @param params     params
+ *  @param iflast     indicate that whether this func will be reused
+ */
+- (void)callBack:(NSString *)instanceId funcId:(NSString *)funcId params:(NSString *)params keepAlive:(BOOL)keepAlive;
+
+/**
+ *  CallBack
+ *  @param instanceId:   instance id
+ *  @param funcId    :   callback id
+ *  @param params    :   parameters
+ **/
+- (void)callBack:(NSString *)instanceId funcId:(NSString *)funcId params:(NSString *)params;
+
+/**
+ *  Connect To WebSocket
+ *  @param url       :   url to connect
+ **/
+- (void)connectToWebSocket:(NSURL *)url;
+
+/**
+ *  Log To WebSocket
+ *  @param flag      :   the tag to indentify
+ *  @param message   :   message to output
+ **/
+- (void)logToWebSocket:(NSString *)flag message:(NSString *)message;
+
+/**
+ *  Reset Environment
+ **/
+- (void)resetEnvironment;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
new file mode 100644
index 0000000..474bd92
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m
@@ -0,0 +1,239 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+#import "WXBridgeManager.h"
+#import "WXBridgeContext.h"
+#import "WXLog.h"
+#import "WXAssert.h"
+
+@interface WXBridgeManager ()
+
+@property (nonatomic, strong) WXBridgeContext   *bridgeCtx;
+@property (nonatomic, strong) NSThread  *jsThread;
+@property (nonatomic, assign) BOOL  stopRunning;
+
+@end
+
+static NSThread *WXBridgeThread;
+
+@implementation WXBridgeManager
+
+- (instancetype)init
+{
+    self = [super init];
+    if (self) {
+        _bridgeCtx = [[WXBridgeContext alloc] init];
+        
+        _jsThread = [[NSThread alloc] initWithTarget:self selector:@selector(_runLoopThread) object:nil];
+        [_jsThread setName: WX_BRIDGE_THREAD_NAME];
+        
+        if (WX_SYS_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) {
+            [_jsThread setQualityOfService:[[NSThread mainThread] qualityOfService]];
+        } else {
+            [_jsThread setThreadPriority:[[NSThread mainThread] threadPriority]];
+        }
+
+        [_jsThread start];
+    }
+    return self;
+}
+
+- (void)unload
+{
+    if (_bridgeCtx) {
+        _bridgeCtx = [[WXBridgeContext alloc] init];
+    }
+}
+
+#pragma mark Thread Management
+
+- (void)_runLoopThread
+{
+    [[NSRunLoop currentRunLoop] addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
+    
+    while (!_stopRunning) {
+        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
+    }
+}
+
+#define WXPerformBlockOnBridgeThread(block) \
+do{\
+    dispatch_block_t pBlock = block; \
+    [self _performBlockOnBridgeThread:pBlock];\
+}while(0)
+
+- (void)_performBlockOnBridgeThread:(void (^)())block
+{
+    if ([NSThread currentThread] == _jsThread) {
+        block();
+    } else {
+        [self performSelector:@selector(_performBlockOnBridgeThread:)
+                     onThread:_jsThread
+                   withObject:[block copy]
+                waitUntilDone:NO];
+    }
+}
+
+#pragma mark JSBridge Management
+
+- (void)createInstance:(NSString *)instance
+              template:(NSString *)temp
+               options:(NSDictionary *)options
+                  data:(id)data
+{
+    if (!instance || !temp) return;
+    
+    __weak typeof(self) weakSelf = self;
+    WXPerformBlockOnBridgeThread(^(){
+        [weakSelf.bridgeCtx createInstance:instance
+                                  template:temp
+                                   options:options
+                                      data:data];
+    });
+}
+
+- (void)destroyInstance:(NSString *)instance
+{
+    if (!instance) return;
+    
+    __weak typeof(self) weakSelf = self;
+    WXPerformBlockOnBridgeThread(^(){
+        [weakSelf.bridgeCtx destroyInstance:instance];
+    });
+}
+
+- (void)refreshInstance:(NSString *)instance
+                   data:(NSDictionary *)data
+{
+    if (!instance) return;
+    
+    __weak typeof(self) weakSelf = self;
+    WXPerformBlockOnBridgeThread(^(){
+        [weakSelf.bridgeCtx refreshInstance:instance data:data];
+    });
+}
+
+- (void)updateState:(NSString *)instance data:(id)data
+{
+    if (!instance) return;
+    
+    __weak typeof(self) weakSelf = self;
+    WXPerformBlockOnBridgeThread(^(){
+        [weakSelf.bridgeCtx updateState:instance data:data];
+    });
+}
+
+- (void)executeJsFramework:(NSString *)script
+{
+    if (!script) return;
+    
+    __weak typeof(self) weakSelf = self;
+    WXPerformBlockOnBridgeThread(^(){
+        [weakSelf.bridgeCtx executeJsFramework:script];
+    });
+}
+
+- (void)executeJsMethod:(WXBridgeMethod *)method
+{
+    if (!method) return;
+    
+    __weak typeof(self) weakSelf = self;
+    WXPerformBlockOnBridgeThread(^(){
+        [weakSelf.bridgeCtx executeJsMethod:method];
+    });
+}
+
+- (void)registerModules:(NSDictionary *)modules
+{
+    if (!modules) return;
+    
+    __weak typeof(self) weakSelf = self;
+    WXPerformBlockOnBridgeThread(^(){
+        [weakSelf.bridgeCtx registerModules:modules];
+    });
+}
+
+- (void)registerComponents:(NSArray *)components
+{
+    if (!components) return;
+    
+    __weak typeof(self) weakSelf = self;
+    WXPerformBlockOnBridgeThread(^(){
+        [weakSelf.bridgeCtx registerComponents:components];
+    });
+}
+
+- (void)fireEvent:(NSString *)instanceId ref:(NSString *)ref type:(NSString *)type params:(NSDictionary *)params
+{
+    if (!type || !ref) {
+        WXLogError(@"Event type and component ref should not be nil");
+        return;
+    }
+    
+    NSArray *args = nil;
+    if (params) {
+       args = @[ref, type, params];
+    } else {
+        args = @[ref, type];
+    }
+    NSMutableDictionary *methodDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+                                       @"fireEvent", @"method",
+                                       args, @"args", nil];
+    WXBridgeMethod *method = [[WXBridgeMethod alloc] initWithInstance:instanceId data:methodDict];
+    [self executeJsMethod:method];
+}
+
+- (void)callBack:(NSString *)instanceId funcId:(NSString *)funcId params:(NSString *) params keepAlive:(BOOL)keepAlive {
+    NSArray *args = nil;
+    if (keepAlive) {
+        args = @[[funcId copy], params? [params copy]:@"\"{}\"", @true];
+    }else {
+        args = @[[funcId copy], params? [params copy]:@"\"{}\""];
+    }
+    NSMutableDictionary *methodDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+                                       @"callback", @"method",
+                                       @"jsBridge",@"module",
+                                       args, @"args", nil];
+    
+    WXBridgeMethod *method = [[WXBridgeMethod alloc] initWithInstance:instanceId data:methodDict];
+    
+    [self executeJsMethod:method];
+}
+
+- (void)callBack:(NSString *)instanceId funcId:(NSString *)funcId params:(NSString *)params
+{
+    [self callBack:instanceId funcId:funcId params:params keepAlive:NO];
+}
+
+- (void)connectToWebSocket:(NSURL *)url
+{
+    __weak typeof(self) weakSelf = self;
+    WXPerformBlockOnBridgeThread(^(){
+        [weakSelf.bridgeCtx connectToWebSocket:url];
+    });
+}
+
+- (void)logToWebSocket:(NSString *)flag message:(NSString *)message
+{
+    if (!message) return;
+    
+    __weak typeof(self) weakSelf = self;
+    WXPerformBlockOnBridgeThread(^(){
+        [weakSelf.bridgeCtx logToWebSocket:flag message:message];
+    });
+}
+
+- (void)resetEnvironment
+{
+    __weak typeof(self) weakSelf = self;
+    WXPerformBlockOnBridgeThread(^(){
+        [weakSelf.bridgeCtx resetEnvironment];
+    });
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/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
new file mode 100644
index 0000000..43be42f
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.h
@@ -0,0 +1,35 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface WXComponentFactory : NSObject
+
+/**
+ * @abstract Register a component for a given name
+ *
+ * @param name The component name to register;
+ * @param clazz The WXComponent subclass to register
+ */
++ (void)registerComponent:(NSString *)name withClass:(Class)clazz;
+
+/**
+ * @abstract Register a list of components
+ * @param components The components array to register, every element in array should be a dictionary,  in the form of @{@"name": @"xxx", @"class":@"yyy"}, which specifies the name and class of the component
+ */
++ (void)registerComponents:(NSArray *)components;
+
+/**
+ * @abstract Returns the class with a given component name.
+ * @param name The component's name
+ * @return The component's class
+ */
++ (Class)classWithComponentName:(NSString *)name;
+
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/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
new file mode 100644
index 0000000..43bfc0f
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentFactory.m
@@ -0,0 +1,139 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+#import "WXComponentFactory.h"
+#import "WXAssert.h"
+#import "WXLog.h"
+
+@interface WXComponentConfig : NSObject
+
+@property (nonatomic, strong) NSString *name;
+@property (nonatomic, strong) NSString *clazz;
+
+- (instancetype)initWithName:(NSString *)name class:(NSString *)clazz;
+
+@end
+
+@implementation WXComponentConfig
+
+- (instancetype)initWithName:(NSString *)name class:(NSString *)clazz
+{
+    if (self = [super init]) {
+        _name = name;
+        _clazz = clazz;
+    }
+    
+    return self;
+}
+
+@end
+
+@implementation WXComponentFactory
+{
+    NSMutableDictionary *_componentConfigs;
+    NSLock *_configLock;
+}
+
+#pragma mark Life Cycle
+
++ (instancetype)sharedInstance {
+    static id _sharedInstance = nil;
+    static dispatch_once_t oncePredicate;
+    dispatch_once(&oncePredicate, ^{
+        _sharedInstance = [[self alloc] init];
+    });
+    return _sharedInstance;
+}
+
+- (instancetype)init
+{
+    if(self = [super init]){
+        _componentConfigs = [NSMutableDictionary dictionary];
+        _configLock = [[NSLock alloc] init];
+    }
+    return self;
+}
+
+#pragma mark Public
+
++ (Class)classWithComponentName:(NSString *)name
+{
+    return [[self sharedInstance] classWithComponentName:name];
+}
+
++ (void)registerComponent:(NSString *)name withClass:(Class)clazz
+{
+    [[self sharedInstance] registerComponent:name withClass:clazz];
+}
+
++ (void)registerComponents:(NSArray *)components
+{
+    [[self sharedInstance] registerComponents:components];
+}
+
+#pragma mark Private
+
+- (Class)classWithComponentName:(NSString *)name
+{
+    WXAssert(name, @"Can not find class for a nil component name");
+    
+    WXComponentConfig *config = nil;
+    
+    [_configLock lock];
+    config = [_componentConfigs objectForKey:name];
+    if (!config) {
+        WXLogWarning(@"No component config for name:%@, use default config", name);
+        config = [_componentConfigs objectForKey:@"div"];
+    }
+    [_configLock unlock];
+    
+    if(!config || !config.clazz) {
+        return nil;
+    }
+    
+    return NSClassFromString(config.clazz);
+}
+
+- (void)registerComponent:(NSString *)name withClass:(Class)clazz
+{
+    WXAssert(name && clazz, @"name or clazz must not be nil for registering component.");
+    
+    WXComponentConfig *config = nil;
+    [_configLock lock];
+    config = [_componentConfigs objectForKey:name];
+    
+    if(config){
+        WXLogInfo(@"Overrider component name:%@ class:%@, to name:%@ class:%@",
+                  config.name, config.class, name, clazz);
+    }
+    
+    config = [[WXComponentConfig alloc] initWithName:name class:NSStringFromClass(clazz)];
+    [_componentConfigs setValue:config forKey:name];
+    [_configLock unlock];
+}
+
+
+- (void)registerComponents:(NSArray *)components
+{
+    WXAssert(components, @"components array must not be nil for registering component.");
+    
+    [_configLock lock];
+    for(NSDictionary *dict in components){
+        NSString *name = dict[@"name"];
+        NSString *clazz = dict[@"class"];
+        WXAssert(name && clazz, @"name or clazz must not be nil for registering components.");
+        
+        WXComponentConfig *config = [[WXComponentConfig alloc] initWithName:name class:clazz];
+        if(config){
+            [_componentConfigs setValue:config forKey:name];
+        }
+    }
+    [_configLock unlock];
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/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
new file mode 100644
index 0000000..d329247
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.h
@@ -0,0 +1,138 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+@class WXSDKInstance;
+@class WXComponent;
+
+extern void WXPerformBlockOnComponentThread(void (^block)());
+
+
+@interface WXComponentManager : NSObject
+
+@property (nonatomic, readonly, weak) WXSDKInstance *weexInstance;
+
+/**
+ * @abstract initialize with weex instance
+ **/
+- (instancetype)initWithWeexInstance:(WXSDKInstance *)weexInstance;
+
+/**
+ * @abstract return the component thread
+ **/
++ (NSThread *)componentThread;
+
+/**
+ * @abstract starting component tasks
+ **/
+- (void)startComponentTasks;
+
+///--------------------------------------
+/// @name Component Tree Building
+///--------------------------------------
+
+/**
+ * @abstract create root of component tree
+ **/
+- (void)createRoot:(NSDictionary *)data;
+
+/**
+ * @abstract add component
+ **/
+- (void)addComponent:(NSDictionary *)componentData toSupercomponent:(NSString *)superRef atIndex:(NSInteger)index appendingInTree:(BOOL)appendingInTree;
+
+/**
+ * @abstract remove component
+ **/
+- (void)removeComponent:(NSString *)ref;
+
+/**
+ * @abstract move component
+ **/
+- (void)moveComponent:(NSString *)ref toSuper:(NSString *)superRef atIndex:(NSInteger)index;
+
+/**
+ * @abstract return component for specific ref
+ */
+- (WXComponent *)componentForRef:(NSString *)ref;
+
+
+///--------------------------------------
+/// @name Updating
+///--------------------------------------
+
+/**
+ * @abstract update styles
+ **/
+- (void)updateStyles:(NSDictionary *)styles forComponent:(NSString *)ref;
+
+/**
+ * @abstract update attributes
+ **/
+- (void)updateAttributes:(NSDictionary *)attributes forComponent:(NSString *)ref;
+
+/**
+ * @abstract add event
+ **/
+- (void)addEvent:(NSString *)event toComponent:(NSString *)ref;
+
+/**
+ * @abstract remove event
+ **/
+- (void)removeEvent:(NSString *)event fromComponent:(NSString *)ref;
+
+/**
+ * @abstract scroll to specific component
+ **/
+- (void)scrollToComponent:(NSString *)ref options:(NSDictionary *)options;
+
+
+///--------------------------------------
+/// @name Life Cycle
+///--------------------------------------
+
+/**
+ * @abstract called when all doms are created
+ **/
+- (void)createFinish;
+
+/**
+ * @abstract called when all doms are refreshed
+ **/
+- (void)refreshFinish;
+
+/**
+ * @abstract called when all doms are updated
+ **/
+- (void)updateFinish;
+
+/**
+ * @abstract unload
+ **/
+- (void)unload;
+
+
+///--------------------------------------
+/// @name Fixed
+///--------------------------------------
+
+/**
+ *  @abstract add a component which has a fixed position
+ *
+ *  @param component
+ */
+- (void)addFixedComponent:(WXComponent *)fixComponent;
+
+/**
+ *  @abstract remove a component which has a fixed position
+ *
+ *  @param component
+ */
+- (void)removeFixedComponent:(WXComponent *)fixComponent;
+
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/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
new file mode 100644
index 0000000..49bac6f
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m
@@ -0,0 +1,545 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+#import "WXComponentManager.h"
+#import "WXComponent.h"
+#import "WXComponent_internal.h"
+#import "WXComponentFactory.h"
+#import "WXDefine.h"
+#import "NSArray+Weex.h"
+#import "WXSDKInstance.h"
+#import "WXAssert.h"
+#import "WXUtility.h"
+#import "WXScrollerProtocol.h"
+
+static NSThread *WXComponentThread;
+
+#define WXAssertComponentExist(component)  WXAssert(component, @"component not exists")
+
+@implementation WXComponentManager
+{
+    __weak WXSDKInstance *_weexInstance;
+    
+    BOOL _stopRunning;
+    NSUInteger _noTaskTickCount;
+    
+    // access only on component thread
+    NSMapTable<NSString *, WXComponent *> *_indexDict;
+    NSMutableArray<dispatch_block_t> *_uiTaskQueue;
+    
+    WXComponent *_rootComponent;
+    NSMutableArray *_fixedComponents;
+    
+    css_node_t *_rootCSSNode;
+    CADisplayLink *_displayLink;
+}
+
++ (instancetype)sharedManager
+{
+    static id _sharedInstance = nil;
+    static dispatch_once_t oncePredicate;
+    dispatch_once(&oncePredicate, ^{
+        _sharedInstance = [[self alloc] init];
+    });
+    return _sharedInstance;
+}
+
+- (instancetype)initWithWeexInstance:(id)weexInstance
+{
+    if (self = [self init]) {
+        _weexInstance = weexInstance;
+        
+        _indexDict = [NSMapTable strongToWeakObjectsMapTable];
+        _fixedComponents = [NSMutableArray wx_mutableArrayUsingWeakReferences];
+        _uiTaskQueue = [NSMutableArray array];
+        
+        [self _startDisplayLink];
+    }
+    
+    return self;
+}
+
+- (void)dealloc
+{
+}
+
+#pragma mark Thread Management
+
++ (NSThread *)componentThread
+{
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        WXComponentThread = [[NSThread alloc] initWithTarget:[self sharedManager] selector:@selector(_runLoopThread) object:nil];
+        [WXComponentThread setName:WX_COMPONENT_THREAD_NAME];
+        if(WX_SYS_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) {
+            [WXComponentThread setQualityOfService:[[NSThread mainThread] qualityOfService]];
+        } else {
+            [WXComponentThread setThreadPriority:[[NSThread mainThread] threadPriority]];
+        }
+        
+        [WXComponentThread start];
+    });
+    
+    return WXComponentThread;
+}
+
+- (void)_runLoopThread
+{
+    [[NSRunLoop currentRunLoop] addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
+    
+    while (!_stopRunning) {
+        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
+    }
+}
+
++ (void)_performBlockOnComponentThread:(void (^)())block
+{
+    if([NSThread currentThread] == [self componentThread]){
+        block();
+    } else {
+        [self performSelector:@selector(_performBlockOnComponentThread:)
+                     onThread:WXComponentThread
+                   withObject:[block copy]
+                waitUntilDone:NO];
+    }
+}
+
+- (void)startComponentTasks
+{
+    [self _awakeDisplayLink];
+}
+
+- (void)_addUITask:(void (^)())block
+{
+    [_uiTaskQueue addObject:block];
+}
+
+#pragma mark Component Tree Building
+
+- (void)createRoot:(NSDictionary *)data
+{
+    WXAssertComponentThread();
+    WXAssertParam(data);
+    
+    WXComponent *rootComponent = [self _buildComponentForData:data];
+    _rootComponent = rootComponent;
+    WXSDKInstance *instance = self.weexInstance;
+    instance.rootView.wx_component = rootComponent;
+    
+    _rootCSSNode = new_css_node();
+    _rootCSSNode->style.position[CSS_LEFT] = instance.frame.origin.x;
+    _rootCSSNode->style.position[CSS_TOP] = instance.frame.origin.y;
+    _rootCSSNode->style.dimensions[CSS_WIDTH] = instance.frame.size.width;
+    _rootCSSNode->style.dimensions[CSS_HEIGHT] = instance.frame.size.height;
+    _rootCSSNode->style.flex_wrap = CSS_NOWRAP;
+    _rootCSSNode->is_dirty = rootNodeIsDirty;
+    _rootCSSNode->get_child = rootNodeGetChild;
+    _rootCSSNode->context = (__bridge void *)(self);
+    _rootCSSNode->children_count = 1;
+
+    
+    [self _addUITask:^{
+        [instance.rootView addSubview:rootComponent.view];
+    }];
+}
+
+static bool rootNodeIsDirty(void *context)
+{
+    WXComponentManager *mananger = (__bridge WXComponentManager *)(context);
+    return [mananger->_rootComponent needsLayout];
+}
+
+static css_node_t * rootNodeGetChild(void *context, int i)
+{
+    WXComponentManager *mananger = (__bridge WXComponentManager *)(context);
+    if (i == 0) {
+        return mananger->_rootComponent.cssNode;
+    } else if(mananger->_fixedComponents.count > 0) {
+        return ((WXComponent *)((mananger->_fixedComponents)[i-1])).cssNode;
+    }
+    
+    return NULL;
+}
+
+- (void)addComponent:(NSDictionary *)componentData toSupercomponent:(NSString *)superRef atIndex:(NSInteger)index appendingInTree:(BOOL)appendingInTree
+{
+    WXAssertComponentThread();
+    WXAssertParam(componentData);
+    WXAssertParam(superRef);
+    
+    WXComponent *supercomponent = [_indexDict objectForKey:superRef];
+    WXAssertComponentExist(supercomponent);
+    
+    [self _recursivelyAddComponent:componentData toSupercomponent:supercomponent atIndex:index appendingInTree:appendingInTree];
+}
+
+- (void)_recursivelyAddComponent:(NSDictionary *)componentData toSupercomponent:(WXComponent *)supercomponent atIndex:(NSInteger)index appendingInTree:(BOOL)appendingInTree
+{
+     WXComponent *component = [self _buildComponentForData:componentData];
+    
+    index = (index == -1 ? supercomponent.subcomponents.count : index);
+    
+    [supercomponent _insertSubcomponent:component atIndex:index];
+    
+    [self _addUITask:^{
+        [supercomponent insertSubview:component atIndex:index];
+    }];
+
+    NSArray *subcomponentsData = [componentData valueForKey:@"children"];
+    
+    BOOL appendTree = !appendingInTree && [component.attributes[@"append"] isEqualToString:@"tree"];
+    // if ancestor is appending tree, child should not be laid out again even it is appending tree.
+    for(NSDictionary *subcomponentData in subcomponentsData){
+        [self _recursivelyAddComponent:subcomponentData toSupercomponent:component atIndex:-1 appendingInTree:appendTree || appendingInTree];
+    }
+    if (appendTree) {
+        // If appending tree,force layout in case of too much tasks piling up in syncQueue
+        [self _layoutAndSyncUI];
+    }
+}
+
+- (void)moveComponent:(NSString *)ref toSuper:(NSString *)superRef atIndex:(NSInteger)index
+{
+    WXAssertComponentThread();
+    WXAssertParam(ref);
+    WXAssertParam(superRef);
+    
+    WXComponent *component = [_indexDict objectForKey:ref];
+    WXComponent *newSupercomponent = [_indexDict objectForKey:superRef];
+    WXAssertComponentExist(component);
+    WXAssertComponentExist(newSupercomponent);
+    
+    if (component.supercomponent == newSupercomponent && [newSupercomponent.subcomponents indexOfObject:component] < index) {
+        // if the supercomponent moved to is the same as original supercomponent,
+        // unify it into the index after removing.
+        index--;
+    }
+    
+    [component _moveToSupercomponent:newSupercomponent atIndex:index];
+    
+    [self _addUITask:^{
+        [component moveToSuperview:newSupercomponent atIndex:index];
+    }];
+}
+
+- (void)removeComponent:(NSString *)ref
+{
+    WXAssertComponentThread();
+    WXAssertParam(ref);
+    
+    WXComponent *component = [_indexDict objectForKey:ref];
+    WXAssertComponentExist(component);
+    
+    [component _removeFromSupercomponent];
+    
+    [_indexDict removeObjectForKey:ref];
+    
+    [self _addUITask:^{
+        [component removeFromSuperview];
+    }];
+}
+
+- (WXComponent *)componentForRef:(NSString *)ref
+{
+    NSDictionary *dict = [_indexDict copy];
+    return [dict objectForKey:ref];
+}
+
+
+- (WXComponent *)_buildComponentForData:(NSDictionary *)data
+{
+    NSString *ref = data[@"ref"];
+    NSString *type = data[@"type"];
+    NSDictionary *styles = data[@"style"];
+    NSDictionary *attributes = data[@"attr"];
+    NSArray *events = data[@"event"];
+    
+    Class clazz = [WXComponentFactory classWithComponentName:type];
+    WXComponent *component = [[clazz alloc] initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:self.weexInstance];
+    WXAssert(component, @"Component build failed for data:%@", data);
+    
+    [_indexDict setObject:component forKey:component.ref];
+    
+    return component;
+}
+
+#pragma mark Updating
+
+- (void)updateStyles:(NSDictionary *)styles forComponent:(NSString *)ref
+{
+    WXAssertParam(styles);
+    WXAssertParam(ref);
+    
+    WXComponent *component = [_indexDict objectForKey:ref];
+    WXAssertComponentExist(component);
+    
+    [component _updateStylesOnComponentThread:styles];
+    [self _addUITask:^{
+        [component _updateStylesOnMainThread:styles];
+    }];
+}
+
+- (void)updateAttributes:(NSDictionary *)attributes forComponent:(NSString *)ref
+{
+    WXAssertParam(attributes);
+    WXAssertParam(ref);
+    
+    WXComponent *component = [_indexDict objectForKey:ref];
+    WXAssertComponentExist(component);
+    
+    [component _updateAttributesOnComponentThread:attributes];
+    [self _addUITask:^{
+        [component _updateAttributesOnMainThread:attributes];
+    }];
+}
+
+- (void)addEvent:(NSString *)eventName toComponent:(NSString *)ref
+{
+    WXAssertComponentThread();
+    WXAssertParam(eventName);
+    WXAssertParam(ref);
+    
+    WXComponent *component = [_indexDict objectForKey:ref];
+    WXAssertComponentExist(component);
+    
+    [component _addEventOnComponentThread:eventName];
+    
+    [self _addUITask:^{
+        [component _addEventOnMainThread:eventName];
+    }];
+}
+
+- (void)removeEvent:(NSString *)eventName fromComponent:(NSString *)ref
+{
+    WXAssertComponentThread();
+    WXAssertParam(eventName);
+    WXAssertParam(ref);
+    
+    WXComponent *component = [_indexDict objectForKey:ref];
+    WXAssertComponentExist(component);
+    
+    [component _removeEventOnComponentThread:eventName];
+    
+    [self _addUITask:^{
+        [component _removeEventOnMainThread:eventName];
+    }];
+}
+
+- (void)scrollToComponent:(NSString *)ref options:(NSDictionary *)options
+{
+    WXAssertComponentThread();
+    WXAssertParam(ref);
+    
+    WXComponent *toComponent = [_indexDict objectForKey:ref];
+    WXAssertComponentExist(toComponent);
+
+    id<WXScrollerProtocol> scrollerComponent = toComponent.ancestorScroller;
+    if (!scrollerComponent) {
+        return;
+    }
+
+    CGFloat offset = [[options objectForKey:@"offset"] floatValue];
+    
+    [self _addUITask:^{
+        [scrollerComponent scrollToComponent:toComponent withOffset:offset];
+    }];
+}
+
+#pragma mark Life Cycle
+
+- (void)createFinish
+{
+    WXAssertComponentThread();
+    
+    WXComponent *root = [_indexDict objectForKey:WX_SDK_ROOT_REF];
+    WXSDKInstance *instance  = self.weexInstance;
+    [self _addUITask:^{        
+        UIView *rootView = root.view;
+        [instance finishPerformance];
+        
+        if(instance.renderFinish){
+            instance.renderFinish(rootView);
+        }
+    }];
+}
+
+- (void)updateFinish
+{
+    WXAssertComponentThread();
+    
+    WXSDKInstance *instance = self.weexInstance;
+    WXComponent *root = [_indexDict objectForKey:WX_SDK_ROOT_REF];
+    
+    [self _addUITask:^{
+        if(instance.updateFinish){
+            instance.updateFinish(root.view);
+        }
+    }];
+}
+
+- (void)refreshFinish
+{
+    WXAssertComponentThread();
+    
+    WXSDKInstance *instance = self.weexInstance;
+    WXComponent *root = [_indexDict objectForKey:WX_SDK_ROOT_REF];
+    
+    [self _addUITask:^{
+        if(instance.refreshFinish){
+            instance.refreshFinish(root.view);
+        }
+    }];
+}
+
+- (void)unload
+{
+    WXAssertComponentThread();
+    
+    for (NSString *key in _indexDict) {
+        WXComponent *component = [_indexDict objectForKey:key];;
+        [self _addUITask:^{
+            [component _unloadView];
+        }];
+    }
+    
+    [_indexDict removeAllObjects];
+    [_uiTaskQueue removeAllObjects];
+    _rootComponent = nil;
+    
+    [self _stopDisplayLink];
+}
+
+#pragma mark Layout Batch
+
+- (void)_startDisplayLink
+{
+    WXAssertComponentThread();
+    
+    if(!_displayLink){
+        _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(_handleDisplayLink)];
+        [_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
+    }
+}
+
+- (void)_stopDisplayLink
+{
+    WXAssertComponentThread();
+    
+    if(_displayLink){
+        [_displayLink invalidate];
+        _displayLink = nil;
+    }
+}
+
+- (void)_suspendDisplayLink
+{
+    WXAssertComponentThread();
+    
+    if(_displayLink && !_displayLink.paused) {
+        _displayLink.paused = YES;
+    }
+}
+
+- (void)_awakeDisplayLink
+{
+    WXAssertComponentThread();
+    
+    if(_displayLink && _displayLink.paused) {
+        _displayLink.paused = NO;
+    }
+}
+
+- (void)_handleDisplayLink
+{
+    WXAssertComponentThread();
+    
+    [self _layoutAndSyncUI];
+}
+
+- (void)_layoutAndSyncUI
+{
+    [self _layout];
+    
+    if(_uiTaskQueue.count > 0){
+        [self _syncUITasks];
+        _noTaskTickCount = 0;
+    } else {
+        // suspend display link when there's no task for 1 second, in order to save CPU time.
+        _noTaskTickCount ++;
+        if (_noTaskTickCount > 60) {
+            [self _suspendDisplayLink];
+        }
+    }
+}
+
+- (void)_layout
+{
+    BOOL needsLayout = NO;
+    for (NSString *ref in _indexDict) {
+        WXComponent *component = [_indexDict objectForKey:ref];
+        
+        if ([component needsLayout]) {
+            needsLayout = YES;
+        }
+    }
+    
+    if (!needsLayout) {
+        return;
+    }
+    
+    layoutNode(_rootCSSNode, _rootCSSNode->style.dimensions[CSS_WIDTH], _rootCSSNode->style.dimensions[CSS_HEIGHT], CSS_DIRECTION_INHERIT);
+    //
+    //    if ([WXLog logLevel] >= WXLogLevelVerbose) {
+    //        print_css_node_NSLog(_cssNode);
+    //    }
+    
+    if ([_rootComponent needsLayout]) {
+//        print_css_node(_rootCSSNode, CSS_PRINT_LAYOUT | CSS_PRINT_STYLE | CSS_PRINT_CHILDREN);
+    }
+    
+    NSMutableSet<WXComponent *> *dirtyComponents = [NSMutableSet set];
+    [_rootComponent _calculateFrameWithSuperAbsolutePosition:CGPointZero gatherDirtyComponents:dirtyComponents];
+    
+    for (WXComponent *dirtyComponent in dirtyComponents) {
+        [self _addUITask:^{
+            [dirtyComponent _layoutDidFinish];
+        }];
+    }
+}
+
+- (void)_syncUITasks
+{
+    NSArray<dispatch_block_t> *blocks = _uiTaskQueue;
+    _uiTaskQueue = [NSMutableArray array];
+    dispatch_async(dispatch_get_main_queue(), ^{
+        for(dispatch_block_t block in blocks) {
+            block();
+        }
+    });
+}
+
+#pragma mark Fixed 
+
+- (void)addFixedComponent:(WXComponent *)fixComponent
+{
+    [_fixedComponents addObject:fixComponent];
+    _rootCSSNode->children_count = (int)[_fixedComponents count] + 1;
+}
+
+- (void)removeFixedComponent:(WXComponent *)fixComponent
+{
+    [_fixedComponents removeObject:fixComponent];
+    _rootCSSNode->children_count = (int)[_fixedComponents count] + 1;
+}
+
+@end
+
+void WXPerformBlockOnComponentThread(void (^block)())
+{
+    [WXComponentManager _performBlockOnComponentThread:block];
+}

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Manager/WXHandlerFactory.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXHandlerFactory.h b/ios/sdk/WeexSDK/Sources/Manager/WXHandlerFactory.h
new file mode 100644
index 0000000..7ad2182
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXHandlerFactory.h
@@ -0,0 +1,29 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface WXHandlerFactory : NSObject
+
+/**
+ * @abstract Register a handler for a given handler instance and specific protocol
+ *
+ * @param handler The handler instance to register
+ *
+ * @param protocol The protocol to confirm
+ *
+ */
++ (void)registerHandler:(id)handler withProtocol:(Protocol *)protocol;
+
+/**
+ * @abstract Returns the handler for a given protocol
+ *
+ **/
++ (id)handlerForProtocol:(Protocol *)protocol;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Manager/WXHandlerFactory.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXHandlerFactory.m b/ios/sdk/WeexSDK/Sources/Manager/WXHandlerFactory.m
new file mode 100644
index 0000000..54a5811
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXHandlerFactory.m
@@ -0,0 +1,49 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+#import "WXHandlerFactory.h"
+#import "WXThreadSafeMutableDictionary.h"
+#import "WXNetworkDefaultImpl.h"
+#import "WXNavigationDefaultImpl.h"
+#import "WXAssert.h"
+
+@interface WXHandlerFactory ()
+
+@property (nonatomic, strong) WXThreadSafeMutableDictionary *handlers;
+
+@end
+
+@implementation WXHandlerFactory
+
++ (instancetype)sharedInstance {
+    static WXHandlerFactory* _sharedInstance = nil;
+    static dispatch_once_t oncePredicate;
+    dispatch_once(&oncePredicate, ^{
+        _sharedInstance = [[self alloc] init];
+        _sharedInstance.handlers = [[WXThreadSafeMutableDictionary alloc] init];
+    });
+    return _sharedInstance;
+}
+
++ (void)registerHandler:(id)handler withProtocol:(Protocol *)protocol
+{
+    WXAssert(handler && protocol, @"Handler or protocol for registering can not be nil.");
+    WXAssertProtocol(handler, protocol);
+        
+    [[WXHandlerFactory sharedInstance].handlers setObject:handler forKey:NSStringFromProtocol(protocol)];
+}
+
++ (id)handlerForProtocol:(Protocol *)protocol
+{
+    WXAssert(protocol, @"Can not find handler for a nil protocol");
+    
+    id handler = [[WXHandlerFactory sharedInstance].handlers objectForKey:NSStringFromProtocol(protocol)];
+    return handler;
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Manager/WXModuleFactory.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXModuleFactory.h b/ios/sdk/WeexSDK/Sources/Manager/WXModuleFactory.h
new file mode 100644
index 0000000..0881cdd
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXModuleFactory.h
@@ -0,0 +1,49 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface WXModuleFactory : NSObject
+
+/**
+ * @abstract Returns the class of specific module
+ *
+ * @param name The module name
+ *
+ **/
++ (Class)classWithModuleName:(NSString *)name;
+
+/**
+ * @abstract Returns the instance method implemented by the module 
+ *
+ * @param name The module name
+ *
+ * @param method The module method
+ *
+ **/
++ (SEL)methodWithModuleName:(NSString *)name withMethod:(NSString *)method;
+
+/**
+ * @abstract Registers a module for a given name and the implemented class
+ *
+ * @param module The module name to register
+ *
+ * @param clazz The module class to register
+ *
+ **/
++ (NSString *)registerModule:(NSString *)name withClass:(Class)clazz;
+
+/**
+ * @abstract Returns the export methods in the specific module
+ *
+ * @param name The module name
+ **/
++ (NSMutableDictionary *)moduleMethodMapsWithName:(NSString *)name;
+       
+@end
+

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Manager/WXModuleFactory.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXModuleFactory.m b/ios/sdk/WeexSDK/Sources/Manager/WXModuleFactory.m
new file mode 100644
index 0000000..3bfa24d
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXModuleFactory.m
@@ -0,0 +1,225 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+#import "WXModuleFactory.h"
+#import "WXAssert.h"
+#import "WXLog.h"
+#import <objc/runtime.h>
+#import <objc/message.h>
+
+/************************************************************************************************/
+
+@interface WXModuleConfig : NSObject
+/**
+ *  The module name
+ **/
+@property (nonatomic, strong) NSString  *name;
+/**
+ *  The module class
+ **/
+@property (nonatomic, strong) NSString  *clazz;
+/**
+ *  The methods map
+ **/
+@property (nonatomic, strong) NSMutableDictionary   *methods;
+
+@end
+
+@implementation WXModuleConfig
+
+- (instancetype)init
+{
+    self = [super init];
+    if (self) {
+        _methods = [NSMutableDictionary dictionary];
+    }
+    return self;
+}
+
+- (void)registerModuleMethods
+{
+    Class currentClass = NSClassFromString(_clazz);
+    
+    if (!currentClass) {
+        WXLogWarning(@"The module class [%@] doesn't exit!", _clazz);
+        return;
+    }
+    
+    while (currentClass != [NSObject class]) {
+        unsigned int methodCount = 0;
+        Method *methodList = class_copyMethodList(object_getClass(currentClass), &methodCount);
+        for (unsigned int i = 0; i < methodCount; i++) {
+            NSString *selStr = [NSString stringWithCString:sel_getName(method_getName(methodList[i])) encoding:NSUTF8StringEncoding];
+            
+            if (![selStr hasPrefix:@"wx_export_method_"]) continue;
+            
+            NSString *name = nil, *method = nil;
+            SEL selector = NSSelectorFromString(selStr);
+            if ([currentClass respondsToSelector:selector]) {
+                method = ((NSString* (*)(id, SEL))[currentClass methodForSelector:selector])(currentClass, selector);
+            }
+            
+            if (method.length <= 0) {
+                WXLogWarning(@"The module class [%@] doesn't has any method!", _clazz);
+                continue;
+            }
+            
+            NSRange range = [method rangeOfString:@":"];
+            if (range.location != NSNotFound) {
+                name = [method substringToIndex:range.location];
+            } else {
+                name = method;
+            }
+            
+            [_methods setObject:method forKey:name];
+        }
+                
+        free(methodList);
+        currentClass = class_getSuperclass(currentClass);
+        
+    }
+}
+
+@end
+
+@interface WXModuleFactory ()
+
+@property (nonatomic, strong)  NSMutableDictionary  *moduleMap;
+@property (nonatomic, strong)  NSLock   *moduleLock;
+
+@end
+
+@implementation WXModuleFactory
+
+static WXModuleFactory *_sharedInstance = nil;
+
+#pragma mark Private Methods
+
++ (WXModuleFactory *)_sharedInstance
+{
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        if (!_sharedInstance) {
+            _sharedInstance = [[self alloc] init];
+        }
+    });
+    return _sharedInstance;
+}
+
++ (instancetype)allocWithZone:(struct _NSZone *)zone
+{
+    if (!_sharedInstance) {
+        _sharedInstance = [super allocWithZone:zone];
+    }
+    return _sharedInstance;
+}
+
+- (instancetype)init
+{
+    @synchronized(self) {
+        self = [super init];
+        if (self) {
+            _moduleMap = [NSMutableDictionary dictionary];
+            _moduleLock = [[NSLock alloc] init];
+        }
+    }
+    return self;
+}
+
+- (Class)_classWithModuleName:(NSString *)name
+{
+    WXAssert(name, @"Fail to find class with module name, please check if the parameter are correct !");
+    
+    WXModuleConfig *config = nil;
+    
+    [_moduleLock lock];
+    config = [_moduleMap objectForKey:name];
+    [_moduleLock unlock];
+    
+    if (!config || !config.clazz) return nil;
+    
+    return NSClassFromString(config.clazz);
+}
+
+- (SEL)_methodWithModuleName:(NSString *)name withMethod:(NSString *)method
+{
+    WXAssert(name && method, @"Fail to find selector with module name and method, please check if the parameters are correct !");
+    
+    NSString *selStr = nil; SEL selector = nil;
+    WXModuleConfig *config = nil;
+    
+    [_moduleLock lock];
+    config = [_moduleMap objectForKey:name];
+    if (config.methods) {
+        selStr = [config.methods objectForKey:method];
+    }
+    if (selStr) {
+        selector = NSSelectorFromString(selStr);
+    }
+    [_moduleLock unlock];
+    
+    return selector;
+}
+
+- (NSString *)_registerModule:(NSString *)name withClass:(Class)clazz
+{
+    WXAssert(name && clazz, @"Fail to register the module, please check if the parameters are correct !");
+    
+    [_moduleLock lock];
+    //allow to register module with the same name;
+    WXModuleConfig *config = [[WXModuleConfig alloc] init];
+    config.name = name;
+    config.clazz = NSStringFromClass(clazz);
+    [config registerModuleMethods];
+    [_moduleMap setValue:config forKey:name];
+    [_moduleLock unlock];
+    
+    return name;
+}
+
+- (NSMutableDictionary *)_moduleMethodMapsWithName:(NSString *)name
+{
+    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
+    NSMutableArray *methods = [NSMutableArray array];
+    
+    [_moduleLock lock];
+    [dict setValue:methods forKey:name];
+    
+    WXModuleConfig *config = _moduleMap[name];
+    void (^mBlock)(id, id, BOOL *) = ^(id mKey, id mObj, BOOL * mStop) {
+        [methods addObject:mKey];
+    };
+    [config.methods enumerateKeysAndObjectsUsingBlock:mBlock];
+    [_moduleLock unlock];
+    
+    return dict;
+}
+
+#pragma mark Public Methods
+
++ (Class)classWithModuleName:(NSString *)name
+{
+    return [[self _sharedInstance] _classWithModuleName:name];
+}
+
++ (SEL)methodWithModuleName:(NSString *)name withMethod:(NSString *)method
+{
+    return [[self _sharedInstance] _methodWithModuleName:name withMethod:method];
+}
+
++ (NSString *)registerModule:(NSString *)name withClass:(Class)clazz
+{
+    return [[self _sharedInstance] _registerModule:name withClass:clazz];
+}
+
++ (NSMutableDictionary *)moduleMethodMapsWithName:(NSString *)name
+{
+    return [[self _sharedInstance] _moduleMethodMapsWithName:name];
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Manager/WXModuleManager.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXModuleManager.h b/ios/sdk/WeexSDK/Sources/Manager/WXModuleManager.h
new file mode 100644
index 0000000..4e66665
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXModuleManager.h
@@ -0,0 +1,16 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+#import <Foundation/Foundation.h>
+#import "WXBridgeMethod.h"
+
+@interface WXModuleManager : NSObject
+
+- (void)dispatchMethod:(WXBridgeMethod *)method;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Manager/WXModuleManager.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXModuleManager.m b/ios/sdk/WeexSDK/Sources/Manager/WXModuleManager.m
new file mode 100644
index 0000000..27cfd1d
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXModuleManager.m
@@ -0,0 +1,139 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+#import "WXModuleManager.h"
+#import "WXModuleProtocol.h"
+#import "WXUtility.h"
+#import "WXModuleFactory.h"
+#import "WXSDKError.h"
+#import "WXSDKManager.h"
+#import "WXThreadSafeMutableDictionary.h"
+#import <objc/message.h>
+
+@interface WXModuleManager ()
+
+@property (nonatomic, strong) WXThreadSafeMutableDictionary *indexDict;
+
+@end
+
+@implementation WXModuleManager
+
+- (instancetype)init
+{
+    self = [super init];
+    if(self){
+        _indexDict = [[WXThreadSafeMutableDictionary alloc]init];
+    }
+    return self;
+}
+
+#pragma mark Private Methods
+
+- (void)_executeModuleThead:(NSThread *)thread withBlock:(dispatch_block_t)block
+{
+    if (!thread || !block) return;
+    
+    if ([NSThread currentThread] == thread) {
+        block();
+    } else {
+        [self performSelector:@selector(_executeModuleBlock:)
+                     onThread:thread
+                   withObject:[block copy]
+                waitUntilDone:NO];
+    }
+}
+
+- (void)_executeModuleBlock:(dispatch_block_t)block
+{
+    if (block) block();
+}
+
+- (void)_executeModuleMethod:(id)module withMethod:(WXBridgeMethod *)method
+{
+    if (!module) return;
+    
+    SEL selector = [WXModuleFactory methodWithModuleName:method.module withMethod:method.method];
+    NSArray *arguments = method.arguments;
+    
+    NSMethodSignature *signature = [module methodSignatureForSelector:selector];
+    if (!signature) {
+        [WXSDKError monitorAlarm:NO errorCode:WA_ERR_INVOKE_NATIVE msg:@"Module:%@, method:%@ doesn't exist !", method.module, method.method];
+        return;
+    }
+    
+    if (signature.numberOfArguments - 2 != method.arguments.count) {
+        [WXSDKError monitorAlarm:NO errorCode:WA_ERR_INVOKE_NATIVE msg:@"Module:%@, the parameters in calling method [%@] and registered method [%@] are not consistent!", method.module, method.method, NSStringFromSelector(selector)];
+        return;
+    }
+    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
+    invocation.target = module;
+    invocation.selector = selector;
+    
+    void **freeList = NULL;
+    WX_ALLOC_FLIST(freeList, arguments.count);
+    
+    for (int i = 0; i < arguments.count; i++) {
+        id obj = arguments[i];
+        const char *parameterType = [signature getArgumentTypeAtIndex:i + 2];
+        static const char *blockType = @encode(typeof(^{}));
+        id argument;
+        if (!strcmp(parameterType, blockType)) {
+            // callback
+            argument = [^void(NSString *result) {
+                NSString* instanceId = method.instance;
+                [[WXSDKManager bridgeMgr] callBack:instanceId funcId:(NSString *)obj params:result];
+            } copy];
+            CFBridgingRetain(argument);
+            [invocation setArgument:&argument atIndex:i + 2];
+        } else {
+            argument = obj;
+            WX_ARGUMENTS_SET(invocation, signature, i, argument, freeList);
+        }
+    }
+    [invocation retainArguments];
+    [invocation invoke];
+    
+    WX_FREE_FLIST(freeList, arguments.count);
+    
+    [WXSDKError monitorAlarm:YES errorCode:WA_ERR_INVOKE_NATIVE msg:@""];
+}
+
+#pragma mark Public Methods
+
+- (void)dispatchMethod:(WXBridgeMethod *)method
+{
+    if (!method) return;
+    
+    Class module =  [WXModuleFactory classWithModuleName:method.module];
+    if (!module) {
+        [WXSDKError monitorAlarm:NO errorCode:WA_ERR_INVOKE_NATIVE msg:@"Module:%@ doesn't exist!", method.module];
+        return;
+    }
+    
+//    WXLogDebug(@"execute:[module %@], [method %@], [parameter %@]", method.module, method.method, method.arguments);
+    
+    WXSDKInstance *weexInstance = [WXSDKManager instanceForID:method.instance];
+    id<WXModuleProtocol> moduleInstance = [weexInstance moduleForClass:module];
+    
+    // attach target thread
+    NSThread *targetThread = nil;
+    if([moduleInstance respondsToSelector:@selector(targetExecuteThread)]){
+        targetThread = [moduleInstance targetExecuteThread];
+    } else {
+        targetThread = [NSThread mainThread];
+    }
+    
+    //execute module method
+    __weak typeof(self) weakSelf = self;
+    dispatch_block_t dipatchMethodBlock = ^ (){
+        [weakSelf _executeModuleMethod:moduleInstance withMethod:method];
+    };
+    [self _executeModuleThead:targetThread withBlock:dipatchMethodBlock];
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Manager/WXSDKManager.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXSDKManager.h b/ios/sdk/WeexSDK/Sources/Manager/WXSDKManager.h
new file mode 100644
index 0000000..1f345a4
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXSDKManager.h
@@ -0,0 +1,41 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+#import <Foundation/Foundation.h>
+#import "WXBridgeManager.h"
+#import "WXModuleManager.h"
+#import "WXSDKInstance.h"
+
+@interface WXSDKManager : NSObject
+
+/**
+ * @abstract Returns bridge manager
+ **/
++ (WXBridgeManager *)bridgeMgr;
+
+/**
+ * @abstract Returns module manager
+ **/
++ (WXModuleManager *)moduleMgr;
+
+/**
+ * @abstract Returns weex instance for specific identifier
+ **/
++ (WXSDKInstance *)instanceForID:(NSString *)identifier;
+
+/**
+ * @abstract Returns weex instance for specific identifier
+ **/
++ (void)storeInstance:(WXSDKInstance *)instance forID:(NSString *)identifier;
+
+/**
+ * @abstract Returns weex instance for specific identifier
+ **/
++ (void)removeInstanceforID:(NSString *)identifier;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Manager/WXSDKManager.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXSDKManager.m b/ios/sdk/WeexSDK/Sources/Manager/WXSDKManager.m
new file mode 100644
index 0000000..fcebce2
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXSDKManager.m
@@ -0,0 +1,73 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+#import "WXSDKManager.h"
+#import "WXThreadSafeMutableDictionary.h"
+
+@interface WXSDKManager ()
+
+@property (nonatomic, strong) WXBridgeManager *bridgeMgr;
+
+@property (nonatomic, strong) WXModuleManager *moduleMgr;
+
+@property (nonatomic, strong) WXThreadSafeMutableDictionary *instanceDict;
+
+@end
+
+@implementation WXSDKManager
+
+static WXSDKManager *_sharedInstance = nil;
+
++ (WXSDKManager *)sharedInstance
+{
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        if (!_sharedInstance) {
+            _sharedInstance = [[self alloc] init];
+            _sharedInstance.instanceDict = [[WXThreadSafeMutableDictionary alloc] init];
+        }
+    });
+    return _sharedInstance;
+}
+
++ (WXBridgeManager *)bridgeMgr
+{
+    WXBridgeManager *bridgeMgr = [self sharedInstance].bridgeMgr;
+    if (!bridgeMgr) {
+        bridgeMgr = [[WXBridgeManager alloc] init];
+        [self sharedInstance].bridgeMgr = bridgeMgr;
+    }
+    return bridgeMgr;
+}
+
++ (WXModuleManager *)moduleMgr
+{
+    WXModuleManager *moduleMgr = [self sharedInstance].moduleMgr;
+    if (!moduleMgr) {
+        moduleMgr = [[WXModuleManager alloc] init];
+        [self sharedInstance].moduleMgr = moduleMgr;
+    }
+    return moduleMgr;
+}
+
++ (id)instanceForID:(NSString *)identifier
+{
+    return [[self sharedInstance].instanceDict objectForKey:identifier];
+}
+
++ (void)storeInstance:(WXSDKInstance *)instance forID:(NSString *)identifier
+{
+    [[self sharedInstance].instanceDict setObject:instance forKey:identifier];
+}
+
++ (void)removeInstanceforID:(NSString *)identifier
+{
+    [[self sharedInstance].instanceDict removeObjectForKey:identifier];
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Model/WXBridgeMethod.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXBridgeMethod.h b/ios/sdk/WeexSDK/Sources/Model/WXBridgeMethod.h
new file mode 100644
index 0000000..c3ba7b2
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Model/WXBridgeMethod.h
@@ -0,0 +1,24 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface WXBridgeMethod : NSObject
+
+@property (nonatomic, strong) NSString  *instance;
+@property (nonatomic, strong) NSString  *module;
+@property (nonatomic, strong) NSString  *method;
+@property (nonatomic, strong) NSArray   *arguments;
+
+- (instancetype)initWihData:(NSDictionary *)data;
+
+- (instancetype)initWithInstance:(NSString *)instance data:(NSMutableDictionary *)data;
+
+- (NSDictionary *)dataDesc;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Model/WXBridgeMethod.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXBridgeMethod.m b/ios/sdk/WeexSDK/Sources/Model/WXBridgeMethod.m
new file mode 100644
index 0000000..ae473e9
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Model/WXBridgeMethod.m
@@ -0,0 +1,41 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+#import "WXBridgeMethod.h"
+
+@implementation WXBridgeMethod
+
+- (instancetype)initWihData:(NSDictionary *)data
+{
+    self = [super init];
+    if(self){
+        _module = [data valueForKey:@"module"];
+        _method = [data valueForKey:@"method"];
+        _arguments = [data valueForKey:@"args"];
+    }
+    return self;
+}
+
+- (instancetype)initWithInstance:(NSString *)instance data:(NSMutableDictionary *)data
+{
+    self = [self initWihData:data];
+    if (self) {
+        _instance = instance;
+    }
+    return self;
+}
+
+- (NSDictionary *)dataDesc
+{
+    NSString *module = _module ? : @"";
+    NSString *method = _method ? : @"";
+    NSArray *arguments = _arguments ? : @[];
+    return @{@"module":module, @"method":method, @"args":arguments};
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Model/WXComponent+Navigation.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXComponent+Navigation.h b/ios/sdk/WeexSDK/Sources/Model/WXComponent+Navigation.h
new file mode 100644
index 0000000..f3af407
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Model/WXComponent+Navigation.h
@@ -0,0 +1,22 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+#import "WXComponent.h"
+#import "WXNavigationProtocol.h"
+
+@interface WXComponent (Navigation)
+
+- (void)setNavigationBarHidden:(BOOL)hidden;
+
+- (void)setNavigationBackgroundColor:(UIColor *)backgroundColor;
+
+- (void)setNavigationItemWithParam:(NSDictionary *)param position:(WXNavigationItemPosition)position;
+
+- (void)setNavigationWithStyles:(NSDictionary *)styles;
+    
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Model/WXComponent+Navigation.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXComponent+Navigation.m b/ios/sdk/WeexSDK/Sources/Model/WXComponent+Navigation.m
new file mode 100644
index 0000000..7313e4d
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Model/WXComponent+Navigation.m
@@ -0,0 +1,178 @@
+/**
+ * Created by Weex.
+ * Copyright (c) 2016, Alibaba, Inc. All rights reserved.
+ *
+ * This source code is licensed under the Apache Licence 2.0.
+ * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
+ */
+
+#import "WXComponent+Navigation.h"
+#import "WXComponent_internal.h"
+#import "WXSDKInstance_private.h"
+#import "WXBaseViewController.h"
+#import "WXHandlerFactory.h"
+#import "WXConvert.h"
+#import "WXUtility.h"
+
+#define kBarTintColor @"barTintColor"
+#define kBarItemText @"title"
+#define kBarItemTextColor @"titleColor"
+#define kBarItemIcon  @"icon"
+
+#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
+
+@implementation WXComponent (Navigation)
+
+- (id<WXNavigationProtocol>)navigator
+{
+    id<WXNavigationProtocol> navigator = [WXHandlerFactory handlerForProtocol:@protocol(WXNavigationProtocol)];
+    return navigator;
+}
+
+// navigtion configuration
+- (void)_setupNavBarWithStyles:(NSMutableDictionary *)styles attributes:(NSMutableDictionary *)attributes
+{
+    NSString *dataRole = attributes[@"dataRole"];
+    if (dataRole && [dataRole isEqualToString:@"navbar"]) {
+        styles[@"visibility"] = @"hidden";
+        styles[@"position"] = @"fixed";
+        
+        self.weexInstance.naviBarStyles = [NSMutableDictionary new];
+        
+        [self setNavigationBarHidden:NO];
+        
+        NSString *backgroundColor = styles[@"backgroundColor"];
+        [self setNavigationBackgroundColor:[WXConvert UIColor:backgroundColor]];
+    }
+    
+    NSString *position = attributes[@"naviItemPosition"];
+    if (position) {
+        NSMutableDictionary *data = [NSMutableDictionary new];
+        [data setObject:_type forKey:@"type"];
+        [data setObject:styles forKey:@"style"];
+        [data setObject:attributes forKey:@"attr"];
+        
+        if ([position isEqualToString:@"left"]) {
+            [self setNavigationItemWithParam:data position:WXNavigationItemPositionLeft];
+        }
+        else if ([position isEqualToString:@"right"]) {
+            [self setNavigationItemWithParam:data position:WXNavigationItemPositionRight];
+        }
+        else if ([position isEqualToString:@"center"]) {
+            [self setNavigationItemWithParam:data position:WXNavigationItemPositionCenter];
+        }
+    }
+}
+
+- (void)_updateNavBarAttributes:(NSDictionary *)attributes
+{
+    if (attributes[@"data-role"]) {
+        NSString *dataRole = attributes[@"data-role"];
+        if ([dataRole isEqualToString:@"navbar"]) {
+            [self setNavigationBarHidden:NO];
+            
+            NSDictionary *style = self.styles[@"style"];
+            NSString *backgroundColor = style[@"backgroundColor"];
+            [self setNavigationBackgroundColor:[WXConvert UIColor:backgroundColor]];
+        }
+    }
+}
+
+
+- (void)setNavigationBarHidden:(BOOL)hidden
+{
+    UIViewController *container = self.weexInstance.viewController;
+    id<WXNavigationProtocol> navigator = [self navigator];
+    
+    WXPerformBlockOnMainThread(^{
+        [navigator setNavigationBarHidden:hidden animated:NO withContainer:container];
+    });
+}
+
+- (void)setNavigationBackgroundColor:(UIColor *)backgroundColor
+{
+    if (!backgroundColor) return;
+    
+    NSMutableDictionary *styles = self.weexInstance.naviBarStyles;
+    [styles setObject:backgroundColor forKey:kBarTintColor];
+    
+    UIViewController *container = self.weexInstance.viewController;
+    id<WXNavigationProtocol> navigator = [self navigator];
+    
+    WXPerformBlockOnMainThread(^{
+        [navigator setNavigationBackgroundColor:backgroundColor withContainer:container];
+    });
+}
+
+- (void)setNavigationItemWithParam:(NSDictionary *)param position:(WXNavigationItemPosition)position
+{
+    if (!param)  return;
+    
+    __weak __block typeof(WXComponent) *weakSelf = self;
+    
+    NSArray *array = @[@"center",@"right",@"left",@"more"];
+    
+    [self _parse:param resultBlock:^(NSDictionary *dict) {
+        NSMutableDictionary *styles = weakSelf.weexInstance.naviBarStyles;
+        [styles setObject:dict forKey: array[position]];
+        
+        UIViewController *container = weakSelf.weexInstance.viewController;
+        id<WXNavigationProtocol> navigator = [weakSelf navigator];
+        
+        WXPerformBlockOnMainThread(^{
+            [navigator setNavigationItemWithParam:dict position:position completion:nil withContainer:container];
+        });
+    }];
+}
+
+- (void)setNavigationWithStyles:(NSDictionary *)styles
+{
+    UIViewController *container = self.weexInstance.viewController;
+    id<WXNavigationProtocol> navigator = [self navigator];
+
+    if (styles) {
+        [navigator setNavigationBarHidden:NO animated:NO withContainer:container];
+        [navigator setNavigationBackgroundColor:styles[kBarTintColor] withContainer:container];
+        
+        NSArray *array = @[@"center",@"right",@"left",@"more"];
+        [array enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+            [navigator setNavigationItemWithParam:styles[obj] position:idx completion:nil withContainer:container];
+        }];
+    }
+    else {
+        [navigator setNavigationBarHidden:YES animated:NO withContainer:container];
+    }
+}
+
+- (void)_parse:(NSDictionary *)param resultBlock:(void(^)(NSDictionary *))result
+{
+    NSMutableDictionary *dict = [NSMutableDictionary new];
+    NSString *type = param[@"type"];
+    
+    [dict setObject:self.weexInstance.instanceId forKey:@"instanceId"];
+    [dict setObject:self.ref forKey:@"nodeRef"];
+    
+    if ([type isEqualToString:@"text"]) {
+        NSDictionary *attr = param[@"attr"];
+        NSString *title = attr[@"value"];
+        if (title) {
+            [dict setObject:title forKey:kBarItemText];
+        }
+        
+        NSDictionary *style = param[@"style"];
+        NSString *color = style[@"color"];
+        if (color) {
+            [dict setObject:color forKey:kBarItemTextColor];
+        }
+    }
+    else if ([type isEqualToString:@"image"]) {
+        NSDictionary *attr = param[@"attr"];
+        NSString *src = attr[@"src"];
+        if (src) {
+            [dict setObject:src forKey:kBarItemIcon];
+        }
+    }
+    result(dict);
+}
+
+@end


Mime
View raw message