You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by ji...@apache.org on 2017/01/24 08:18:31 UTC

[16/50] [abbrv] incubator-weex git commit: + [ios] iOS init.

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Component/WXVideoComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXVideoComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXVideoComponent.m
new file mode 100644
index 0000000..18dae99
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/WXVideoComponent.m
@@ -0,0 +1,293 @@
+/**
+ * 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 "WXVideoComponent.h"
+#import <AVFoundation/AVPlayer.h>
+#import <AVKit/AVPlayerViewController.h>
+#import <MediaPlayer/MPMoviePlayerViewController.h>
+#import <MediaPlayer/MPMoviePlayerController.h>
+#import <AVFoundation/AVPlayerItem.h>
+
+@interface WXPlayer : NSObject
+
+@end
+
+@implementation WXPlayer
+
+@end
+
+@interface WXVideoView()
+
+@property (nonatomic, strong) UIViewController* playerViewController;
+
+@end
+
+@implementation WXVideoView
+
+- (id)init
+{
+    if (self = [super init]) {
+        if ([self greater8SysVer]){
+            _playerViewController = [AVPlayerViewController new];
+        } else {
+            _playerViewController = [[MPMoviePlayerViewController alloc] initWithContentURL:nil];
+            MPMoviePlayerViewController *MPVC = (MPMoviePlayerViewController*)_playerViewController;
+            MPVC.moviePlayer.controlStyle = MPMovieControlStyleEmbedded;
+            MPVC.moviePlayer.shouldAutoplay = NO;
+            [[NSNotificationCenter defaultCenter] addObserver:self
+                                                     selector:@selector(playFinish)
+                                                         name:MPMoviePlayerPlaybackDidFinishNotification
+                                                       object:MPVC.moviePlayer];
+            [[NSNotificationCenter defaultCenter] addObserverForName:MPMoviePlayerPlaybackStateDidChangeNotification object:MPVC.moviePlayer queue:nil usingBlock:^(NSNotification *notification)
+             {
+                 if (MPVC.moviePlayer.playbackState == MPMoviePlaybackStatePlaying) {
+                     if (_playbackStateChanged)
+                         _playbackStateChanged(WXPlaybackStatePlaying);
+                 }
+                 if (MPVC.moviePlayer.playbackState == MPMoviePlaybackStateStopped) {
+                     //stopped
+                 } if (MPVC.moviePlayer.playbackState == MPMoviePlaybackStatePaused) {
+                     //paused
+                     if (_playbackStateChanged) {
+                         _playbackStateChanged(WXPlaybackStatePaused);
+                     }
+                 } if (MPVC.moviePlayer.playbackState == MPMoviePlaybackStateInterrupted) {
+                     //interrupted
+                 } if (MPVC.moviePlayer.playbackState == MPMoviePlaybackStateSeekingForward) {
+                     //seeking forward
+                 } if (MPVC.moviePlayer.playbackState == MPMoviePlaybackStateSeekingBackward) {
+                     //seeking backward
+                 }
+             }];
+        }
+        
+        [self addSubview:_playerViewController.view];
+    }
+    return self;
+}
+
+- (void)dealloc
+{
+    if ([self greater8SysVer]){
+        AVPlayerViewController *AVVC = (AVPlayerViewController*)_playerViewController;
+        [AVVC.player removeObserver:self forKeyPath:@"rate"];
+        [AVVC.player.currentItem removeObserver:self forKeyPath:@"status"];
+        
+        [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:AVVC.player.currentItem];
+    }
+    else {
+        MPMoviePlayerViewController *MPVC = (MPMoviePlayerViewController*)_playerViewController;
+        [[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackStateDidChangeNotification object:MPVC.moviePlayer];
+        [[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:MPVC.moviePlayer];
+    }
+}
+
+- (BOOL)greater8SysVer
+{
+    //return NO;
+    NSString *reqSysVer = @"8.0";
+    NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
+    return [currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending;
+}
+
+- (void)observeValueForKeyPath:(NSString *)keyPath
+                      ofObject:(id)object
+                        change:(NSDictionary<NSString *,id> *)change
+                       context:(void *)context
+{
+    if ([keyPath isEqualToString:@"rate"]) {
+        float rate = [change[NSKeyValueChangeNewKey] floatValue];
+        if (rate == 0.0) {
+            if (_playbackStateChanged)
+                _playbackStateChanged(WXPlaybackStatePaused);
+        } else if (rate == 1.0) {
+            if (_playbackStateChanged)
+                _playbackStateChanged(WXPlaybackStatePlaying);
+        } else if (rate == -1.0) {
+            // Reverse playback
+        }
+    }
+    else if ([keyPath isEqualToString:@"status"]) {
+        NSInteger status = [change[NSKeyValueChangeNewKey] integerValue];
+        if (status == AVPlayerStatusFailed) {
+            if (_playbackStateChanged)
+                _playbackStateChanged(WXPlaybackStateFailed);
+        }
+    }
+}
+
+- (void)setFrame:(CGRect)frame
+{
+    [super setFrame:frame];
+    
+    CGRect videoFrame = frame;
+    videoFrame.origin.x = 0;
+    videoFrame.origin.y = 0;
+    [_playerViewController.view setFrame:videoFrame];
+}
+
+- (void)setURL:(NSURL *)URL
+{
+    if ([self greater8SysVer]){
+        
+        AVPlayerViewController *AVVC = (AVPlayerViewController*)_playerViewController;
+        if (AVVC.player && AVVC.player.currentItem) {
+            [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:AVVC.player.currentItem];
+            [AVVC.player.currentItem removeObserver:self forKeyPath:@"status"];
+        }
+        AVPlayer *player = [AVPlayer playerWithURL:URL];
+        AVVC.player = player;
+        
+        [player addObserver:self
+                 forKeyPath:@"rate"
+                    options:NSKeyValueObservingOptionNew
+                    context:NULL];
+        
+        [player.currentItem addObserver:self
+                             forKeyPath:@"status"
+                                options:NSKeyValueObservingOptionNew
+                                context:NULL];
+        
+        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playFinish) name:AVPlayerItemDidPlayToEndTimeNotification object:player.currentItem];
+    }
+    else {
+        MPMoviePlayerViewController *MPVC = (MPMoviePlayerViewController*)_playerViewController;
+        [MPVC moviePlayer].contentURL = URL;
+    }
+}
+
+- (void)playFinish
+{
+    if (_playbackStateChanged)
+        _playbackStateChanged(WXPlaybackStatePlayFinish);
+    if ([self greater8SysVer]) {
+        AVPlayerViewController *AVVC = (AVPlayerViewController*)_playerViewController;
+        [[AVVC player] seekToTime:CMTimeMultiply([AVVC player].currentTime, 0)];
+    } else {
+        MPMoviePlayerViewController *MPVC = (MPMoviePlayerViewController*)_playerViewController;
+        [[MPVC moviePlayer] stop];
+    }
+}
+
+- (void)play
+{
+    if ([self greater8SysVer]) {
+        AVPlayerViewController *AVVC = (AVPlayerViewController*)_playerViewController;
+
+        [[AVVC player] play];
+    } else {
+        MPMoviePlayerViewController *MPVC = (MPMoviePlayerViewController*)_playerViewController;
+        [[MPVC moviePlayer] play];
+    }
+}
+
+- (void)pause
+{
+    if ([self greater8SysVer]){
+        AVPlayerViewController *AVVC = (AVPlayerViewController*)_playerViewController;
+        [[AVVC player] pause];
+    } else {
+        MPMoviePlayerViewController *MPVC = (MPMoviePlayerViewController*)_playerViewController;
+        [[MPVC moviePlayer] pause];
+    }
+}
+
+@end
+
+@interface WXVideoComponent()
+
+@property (nonatomic, strong) WXVideoView *videoView;
+@property (nonatomic, strong) NSURL *videoURL;
+@property (nonatomic) BOOL autoPlay;
+@property (nonatomic) BOOL playStatus;
+
+@end
+
+@implementation WXVideoComponent
+
+- (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDictionary *)styles attributes:(NSDictionary *)attributes events:(NSArray *)events weexInstance:(WXSDKInstance *)weexInstance {
+    self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance];
+    if (self) {
+        if (attributes[@"src"]) {
+            _videoURL = [NSURL URLWithString: attributes[@"src"]];
+        }
+        if (attributes[@"autoPlay"]) {
+            _autoPlay = [attributes[@"autoPlay"] boolValue];
+        }
+        if ([attributes[@"playStatus"] compare:@"play" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
+            _playStatus = true;
+        }
+        if ([attributes[@"playStatus"] compare:@"pause" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
+            _playStatus = false;
+        }
+    }
+    return self;
+}
+
+-(UIView *)loadView
+{
+    return [[WXVideoView alloc] init];
+}
+
+-(void)viewDidLoad
+{
+    _videoView = (WXVideoView *)self.view;
+    [_videoView setURL:_videoURL];
+    if (_playStatus) {
+        [_videoView play];
+    } else {
+        [_videoView pause];
+    }
+    if (_autoPlay) {
+        [_videoView play];
+    }
+    __weak __typeof__(self) weakSelf = self;
+    _videoView.playbackStateChanged = ^(WXPlaybackState state) {
+        NSString *eventType = nil;
+        switch (state) {
+            case WXPlaybackStatePlaying:
+                eventType = @"start";
+                break;
+            case WXPlaybackStatePaused:
+                eventType = @"pause";
+                break;
+            case WXPlaybackStatePlayFinish:
+                eventType = @"finish";
+                break;
+            case WXPlaybackStateFailed:
+                eventType = @"fail";
+                break;
+                
+            default:
+                NSCAssert(NO, @"");
+                break;
+        }
+        [weakSelf fireEvent:eventType params:nil];
+    };
+}
+
+-(void)updateAttributes:(NSDictionary *)attributes
+{
+    if (attributes[@"src"]) {
+        _videoURL = [NSURL URLWithString: attributes[@"src"]];
+    }
+    if (attributes[@"autoPlay"]) {
+        _autoPlay = [attributes[@"autoPlay"] boolValue];
+        [_videoView play];
+    }
+    if ([attributes[@"playStatus"] compare:@"play" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
+        _playStatus = true;
+        [_videoView play];
+    }
+    if ([attributes[@"playStatus"] compare:@"pause" options:NSCaseInsensitiveSearch] == NSOrderedSame) {
+        _playStatus = false;
+        [_videoView pause];
+    }
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Component/WXWebComponent.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXWebComponent.h b/ios/sdk/WeexSDK/Sources/Component/WXWebComponent.h
new file mode 100644
index 0000000..f8ed1d0
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/WXWebComponent.h
@@ -0,0 +1,21 @@
+/**
+ * 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"
+
+@interface WXWebComponent : WXComponent<UIWebViewDelegate>
+
+- (void)notifyWebview:(NSDictionary *) data;
+
+- (void)reload;
+
+- (void)goBack;
+
+- (void)goForward;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Component/WXWebComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXWebComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXWebComponent.m
new file mode 100644
index 0000000..3ee5f8d
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/WXWebComponent.m
@@ -0,0 +1,183 @@
+/**
+ * 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 "WXWebComponent.h"
+#import "WXComponent_internal.h"
+#import "WXUtility.h"
+#import <JavaScriptCore/JavaScriptCore.h>
+
+@interface WXWebView : UIWebView
+
+@end
+
+@implementation WXWebView
+
+@end
+
+@interface WXWebComponent ()
+
+@property (nonatomic, strong) JSContext *jsContext;
+
+@property (nonatomic, strong) WXWebView *webview;
+
+@property (nonatomic, strong) NSString *url;
+
+@property (nonatomic, assign) BOOL startLoadEvent;
+
+@property (nonatomic, assign) BOOL finishLoadEvent;
+
+@property (nonatomic, assign) BOOL failLoadEvent;
+
+@property (nonatomic, assign) BOOL notifyEvent;
+
+@end
+
+@implementation WXWebComponent
+
+- (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDictionary *)styles attributes:(NSDictionary *)attributes events:(NSArray *)events weexInstance:(WXSDKInstance *)weexInstance
+{
+    if (self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]) {
+        self.url = attributes[@"src"];
+    }
+    return self;
+}
+
+- (UIView *)loadView
+{
+    return [[WXWebView alloc] init];
+}
+
+- (void)viewDidLoad
+{
+    _webview = (WXWebView *)self.view;
+    _webview.delegate = self;
+    _webview.allowsInlineMediaPlayback = YES;
+    _jsContext = [_webview valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
+    __weak typeof(self) weakSelf = self;
+    _jsContext[@"$notifyWeex"] = ^(JSValue *data) {
+        if (weakSelf.notifyEvent) {
+            [weakSelf fireEvent:@"notify" params:[data toDictionary]];
+        }
+    };
+    
+    if (_url) {
+        [self loadURL:_url];
+    }
+}
+
+- (void)updateAttributes:(NSDictionary *)attributes
+{
+    if (attributes[@"src"]) {
+        self.url = attributes[@"src"];
+    }
+}
+
+- (void)addEvent:(NSString *)eventName
+{
+    if ([eventName isEqualToString:@"pagestart"]) {
+        _startLoadEvent = YES;
+    }
+    else if ([eventName isEqualToString:@"pagefinish"]) {
+        _finishLoadEvent = YES;
+    }
+    else if ([eventName isEqualToString:@"error"]) {
+        _failLoadEvent = YES;
+    }
+}
+
+- (void)setUrl:(NSString *)url
+{
+    if (![url isEqualToString:_url]) {
+        _url = url;
+        
+        if (_url) {
+            [self loadURL:_url];
+        }
+    }
+}
+
+- (void)loadURL:(NSString *)url
+{
+    if (self.webview) {
+        NSURLRequest *request =[NSURLRequest requestWithURL:[NSURL URLWithString:url]];
+        [self.webview loadRequest:request];
+    }
+}
+
+- (void)reload
+{
+    [self.webview reload];
+}
+
+- (void)goBack
+{
+    if ([self.webview canGoBack]) {
+        [self.webview goBack];
+    }
+}
+
+- (void)goForward
+{
+    if ([self.webview canGoForward]) {
+        [self.webview goForward];
+    }
+}
+
+- (void)notifyWebview:(NSDictionary *) data
+{
+    NSString *json = [WXUtility JSONString:data];
+    NSString *code = [NSString stringWithFormat:@"(function(){var evt=null;var data=%@;if(typeof CustomEvent==='function'){evt=new CustomEvent('notify',{detail:data})}else{evt=document.createEvent('CustomEvent');evt.initCustomEvent('notify',true,true,data)}document.dispatchEvent(evt)}())", json];
+    [_jsContext evaluateScript:code];
+}
+
+#pragma mark Webview Delegate
+
+- (NSMutableDictionary<NSString *, id> *)baseInfo
+{
+    NSMutableDictionary<NSString *, id> *info = [NSMutableDictionary new];
+    [info setObject:self.webview.request.URL.absoluteString ?: @"" forKey:@"url"];
+    [info setObject:[self.webview stringByEvaluatingJavaScriptFromString:@"document.title"] ?: @"" forKey:@"title"];
+    [info setObject:@(self.webview.canGoBack) forKey:@"canGoBack"];
+    [info setObject:@(self.webview.canGoForward) forKey:@"canGoForward"];
+    return info;
+}
+
+- (void)webViewDidStartLoad:(UIWebView *)webView
+{
+    
+}
+
+- (void)webViewDidFinishLoad:(UIWebView *)webView
+{
+    if (_finishLoadEvent) {
+        NSDictionary *data = [self baseInfo];
+        [self fireEvent:@"pagefinish" params:data];
+    }
+}
+
+- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
+{
+    if (_failLoadEvent) {
+        NSMutableDictionary *data = [self baseInfo];
+        [data setObject:[error localizedDescription] forKey:@"errorMsg"];
+        [data setObject:[NSString stringWithFormat:@"%ld", (long)error.code] forKey:@"errorCode"];
+        [self fireEvent:@"error" params:data];
+    }
+}
+
+- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
+{
+    if (_startLoadEvent) {
+        NSMutableDictionary<NSString *, id> *data = [NSMutableDictionary new];
+        [data setObject:request.URL.absoluteString ?:@"" forKey:@"url"];
+        [self fireEvent:@"pagestart" params:data];
+    }
+    return YES;
+}
+
+@end
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Controller/WXBaseViewController.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Controller/WXBaseViewController.h b/ios/sdk/WeexSDK/Sources/Controller/WXBaseViewController.h
new file mode 100644
index 0000000..dde47d1
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Controller/WXBaseViewController.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 <UIKit/UIKit.h>
+
+/**
+ * The WXBaseViewController class provides the infrastructure for managing the weex view in your app. It is 
+ * responsible for creating a weex instance or rendering the weex view, for observing the lifecycle of the
+ * view such as "appear" or "disapper"\u3001"foreground" or "background" etc. You can initialize this controller by 
+ * special bundle URL.
+ */
+
+@interface WXBaseViewController : UIViewController <UIGestureRecognizerDelegate>
+
+/**
+ * @abstract initializes the viewcontroller with bundle url.
+ *
+ * @param soureURL. The url of bundle rendered to a weex view.
+ *
+ * @return a object the class of WXBaseViewController.
+ *
+ */
+- (instancetype)initWithSourceURL:(NSURL *)sourceURL;
+
+/**
+ * @abstract refreshes the weex view in controller.
+ */
+- (void)refreshWeex;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Controller/WXBaseViewController.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Controller/WXBaseViewController.m b/ios/sdk/WeexSDK/Sources/Controller/WXBaseViewController.m
new file mode 100644
index 0000000..358451c
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Controller/WXBaseViewController.m
@@ -0,0 +1,186 @@
+/**
+ * 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 "WXBaseViewController.h"
+#import "WXRootViewController.h"
+#import "WXSDKInstance.h"
+#import "WXSDKInstance_private.h"
+#import "WXSDKEngine.h"
+#import "WXUtility.h"
+
+@interface WXBaseViewController ()
+
+@property (nonatomic, strong) WXSDKInstance *instance;
+@property (nonatomic, strong) UIView *weexView;
+@property (nonatomic, strong) NSURL *sourceURL;
+
+@end
+
+@implementation WXBaseViewController
+
+- (void)dealloc
+{
+    [_instance destroyInstance];
+    [self _removeObservers];
+}
+
+- (instancetype)initWithSourceURL:(NSURL *)sourceURL
+{
+    if ((self = [super init])) {
+        self.sourceURL = sourceURL;
+        self.hidesBottomBarWhenPushed = YES;
+        
+        [self _addObservers];
+    }
+    return self;
+}
+
+/**
+ *  After setting the navbar hidden status , this function will be called automatically. In this function, we
+ *  set the height of mainView equal to screen height, because there is something wrong with the layout of
+ *  page content.
+ */
+
+- (void)viewWillLayoutSubviews
+{
+    [super viewWillLayoutSubviews];
+    
+    if ([self.navigationController isKindOfClass:[WXRootViewController class]]) {
+        CGRect frame = self.view.frame;
+        frame.origin.y = 0;
+        frame.size.height = [UIScreen mainScreen].bounds.size.height;
+        self.view.frame = frame;
+    }    
+}
+
+/**
+ *  We assume that the initial state of viewController's navigitonBar is hidden.  By setting the attribute of
+ *  'dataRole' equal to 'navbar', the navigationBar hidden will be NO.
+ */
+- (void)viewDidLoad
+{
+    [super viewDidLoad];
+    [self addEdgePop];
+    self.view.backgroundColor = [UIColor whiteColor];
+    self.automaticallyAdjustsScrollViewInsets = NO;
+    [self _renderWithURL:_sourceURL];
+    
+    if ([self.navigationController isKindOfClass:[WXRootViewController class]]) {
+        self.navigationController.navigationBarHidden = YES;
+    }
+}
+
+- (void)addEdgePop
+{
+    UIScreenEdgePanGestureRecognizer *edgePanGestureRecognizer = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:@selector(edgePanGesture:)];
+    edgePanGestureRecognizer.delegate = self;
+    edgePanGestureRecognizer.edges = UIRectEdgeLeft;
+    [self.view addGestureRecognizer:edgePanGestureRecognizer];
+}
+
+- (void)edgePanGesture:(UIScreenEdgePanGestureRecognizer*)edgePanGestureRecognizer{
+    [self.navigationController popViewControllerAnimated:YES];
+}
+
+#pragma mark- UIGestureRecognizerDelegate
+- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
+    if (!self.navigationController || [self.navigationController.viewControllers count] == 1) {
+        return NO;
+    }
+    return YES;
+}
+
+- (void)viewDidAppear:(BOOL)animated
+{
+    [super viewDidAppear:animated];
+    [self _updateInstanceState:WeexInstanceAppear];
+}
+
+- (void)viewDidDisappear:(BOOL)animated
+{
+    [super viewDidDisappear:animated];
+    [self _updateInstanceState:WeexInstanceDisappear];
+}
+
+- (void)didReceiveMemoryWarning
+{
+    [super didReceiveMemoryWarning];
+    [self _updateInstanceState:WeexInstanceMemoryWarning];
+    // Dispose of any resources that can be recreated.
+}
+
+- (void)refreshWeex
+{
+    [self _renderWithURL:_sourceURL];
+}
+
+- (void)_renderWithURL:(NSURL *)sourceURL
+{
+    if (!sourceURL) {
+        return;
+    }
+
+    [_instance destroyInstance];
+    _instance = [[WXSDKInstance alloc] init];
+    _instance.frame = CGRectMake(0.0f, 0.0f, self.view.bounds.size.width, self.view.bounds.size.height);
+    _instance.pageObject = self;
+    _instance.pageName = [sourceURL absoluteString];
+    _instance.viewController = self;
+    
+    NSString *newURL = nil;
+    
+    if ([sourceURL.absoluteString rangeOfString:@"?"].location != NSNotFound) {
+        newURL = [NSString stringWithFormat:@"%@&random=%d", sourceURL.absoluteString, arc4random()];
+    }
+    else {
+        newURL = [NSString stringWithFormat:@"%@?random=%d", sourceURL.absoluteString, arc4random()];
+    }
+    [_instance renderWithURL:[NSURL URLWithString:newURL] options:@{@"bundleUrl":sourceURL} data:nil];
+    
+    __weak typeof(self) weakSelf = self;
+    _instance.onCreate = ^(UIView *view) {
+        [weakSelf.weexView removeFromSuperview];
+        weakSelf.weexView = view;
+        [weakSelf.view addSubview:weakSelf.weexView];
+    };
+}
+
+- (void)_updateInstanceState:(WXState)state
+{
+    if (_instance) {
+        _instance.state = state;
+    }
+}
+
+- (void)_appStateDidChange:(NSNotification *)nofity
+{
+    if ([nofity.name isEqualToString:@"UIApplicationDidBecomeActiveNotification"]) {
+        [self _updateInstanceState:WeexInstanceForeground];
+    }
+    else if([nofity.name isEqualToString:@"UIApplicationDidEnterBackgroundNotification"]) {
+        [self _updateInstanceState:WeexInstanceBackground]; ;
+    }
+}
+
+- (void)_addObservers
+{
+    for (NSString *name in @[UIApplicationDidBecomeActiveNotification,
+                             UIApplicationDidEnterBackgroundNotification]) {
+        [[NSNotificationCenter defaultCenter] addObserver:self
+                                                 selector:@selector(_appStateDidChange:)
+                                                     name:name
+                                                   object:nil];
+    }
+}
+
+- (void)_removeObservers
+{
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Controller/WXRootViewController.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Controller/WXRootViewController.h b/ios/sdk/WeexSDK/Sources/Controller/WXRootViewController.h
new file mode 100644
index 0000000..5f94c4e
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Controller/WXRootViewController.h
@@ -0,0 +1,33 @@
+/**
+ * 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 <UIKit/UIKit.h>
+
+/**
+ * The WXRootViewController class inherited from UINavigationController class which implements a specialized
+ * view controller that manages the navigation of hierarchical content. Developing an iOS application, you
+ * need a series of customer pages which will be render by weex bundle. Sometimes, these pages are embedded in
+ * viewcontroller. This navigation controller makes it possible to present your page efficiently and makes it
+ * easier for the user to navigate that content.
+ */
+
+@interface WXRootViewController : UINavigationController
+
+/**
+ * @abstract initialize the RootViewController with bundle url.
+ *
+ * @param soureURL. The bundle url which can be render to a weex view.
+ *
+ * @return a object the class of WXRootViewController.
+ *
+ * @discussion initialize this controller in function 'application:didFinishLaunchingWithOptions', and make it as rootViewContoller of window. In the
+ * weex application, all page content can be managed by the navigation, such as push or pop.
+ */
+- (id)initWithSourceURL:(NSURL *)sourceURL;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Controller/WXRootViewController.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Controller/WXRootViewController.m b/ios/sdk/WeexSDK/Sources/Controller/WXRootViewController.m
new file mode 100644
index 0000000..41ebbf7
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Controller/WXRootViewController.m
@@ -0,0 +1,21 @@
+/**
+ * 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 "WXRootViewController.h"
+#import "WXBaseViewController.h"
+
+@implementation WXRootViewController
+
+- (id)initWithSourceURL:(NSURL *)sourceURL
+{
+    WXBaseViewController *baseViewController = [[WXBaseViewController alloc]initWithSourceURL:sourceURL];
+    
+    return [super initWithRootViewController:baseViewController];
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Debug/WXDebugTool.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Debug/WXDebugTool.h b/ios/sdk/WeexSDK/Sources/Debug/WXDebugTool.h
new file mode 100644
index 0000000..3d62aef
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Debug/WXDebugTool.h
@@ -0,0 +1,28 @@
+/**
+ * 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 "WXModuleProtocol.h"
+
+@interface WXDebugTool : NSObject<WXModuleProtocol>
+
+//+ (void)showFPS;
+
++ (void)setDebug:(BOOL)isDebug;
+
++ (BOOL)isDebug;
+
++ (void)setReplacedBundleJS:(NSURL*)url;
+
++ (NSString*)getReplacedBundleJS;
+
++ (void)setReplacedJSFramework:(NSURL*)url;
+
++ (NSString*)getReplacedJSFramework;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Debug/WXDebugTool.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Debug/WXDebugTool.m b/ios/sdk/WeexSDK/Sources/Debug/WXDebugTool.m
new file mode 100644
index 0000000..e5d0b33
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Debug/WXDebugTool.m
@@ -0,0 +1,115 @@
+/**
+ * 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 "WXDebugTool.h"
+//#import "WXFPSLabel.h"
+#import "WXHandlerFactory.h"
+#import "WXNetworkProtocol.h"
+#import "WXUtility.h"
+#import "WXSDKManager.h"
+#import "WXSDKEngine.h"
+
+static BOOL WXIsDebug;
+static NSString* WXDebugrepBundleJS;
+static NSString* WXDebugrepJSFramework;
+
+@implementation WXDebugTool
+
+//+ (void)showFPS
+//{
+//    UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
+//    WXFPSLabel *label = [[WXFPSLabel alloc] initWithFrame:CGRectMake(window.frame.size.width-135, window.frame.size.height-35, 120, 20)];
+//    label.layer.zPosition = MAXFLOAT;
+//    [window addSubview:label];
+//}
+
++ (void)setDebug:(BOOL)isDebug
+{
+    WXIsDebug = isDebug;
+}
+
++ (BOOL)isDebug
+{
+#ifdef DEBUG
+    return YES;
+#endif
+    return WXIsDebug;
+}
+
++ (void)setReplacedBundleJS:(NSURL*)url{
+    [self getData:url key:@"bundlejs"];
+}
+
++ (NSString*)getReplacedBundleJS{
+    return WXDebugrepBundleJS;
+}
+
++ (void)setReplacedJSFramework:(NSURL*)url{
+    [self getData:url key:@"jsframework"];
+}
+
++ (NSString*)getReplacedJSFramework{
+    
+    return WXDebugrepJSFramework;
+}
+
++ (void)getData:(NSURL*)url key:(NSString*)key{
+    void(^scriptLoadFinish)(NSString*, NSString*) = ^(NSString* key, NSString* script){
+        if ([key isEqualToString:@"jsframework"]) {
+            WXDebugrepJSFramework = script;
+            [[WXSDKManager bridgeMgr] unload];
+            [WXSDKEngine initSDKEnviroment:script];
+        }else {
+            WXDebugrepBundleJS = script;
+        }
+    };
+    if ([url isFileURL]) {
+        // File URL
+        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+            NSString *path = [url path];
+            NSData *scriptData = [[NSFileManager defaultManager] contentsAtPath:path];
+            NSString *script = [[NSString alloc] initWithData:scriptData encoding:NSUTF8StringEncoding];
+            if (!script) {
+                NSString *errorDesc = [NSString stringWithFormat:@"File read error at url: %@", url];
+                WXLogError(@"%@", errorDesc);
+            }
+            scriptLoadFinish(key, script);
+        });
+    } else {
+        // HTTP/HTTPS URL
+        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
+        [request setValue:[WXUtility userAgent] forHTTPHeaderField:@"User-Agent"];
+        
+        id<WXNetworkProtocol> networkHandler = [WXHandlerFactory handlerForProtocol:@protocol(WXNetworkProtocol)];
+        
+        __block NSURLResponse *urlResponse;
+        [networkHandler sendRequest:request
+                    withSendingData:^(int64_t bytesSent, int64_t totalBytes) {}
+                       withResponse:^(NSURLResponse *response) {
+                           urlResponse = response;
+                       }
+                    withReceiveData:^(NSData *data) {}
+                    withCompeletion:^(NSData *totalData, NSError *error) {
+                        if (error) {
+                            
+                        } else {
+                            if ([urlResponse isKindOfClass:[NSHTTPURLResponse class]] && ((NSHTTPURLResponse *)urlResponse).statusCode != 200) {
+                                __unused NSError *error = [NSError errorWithDomain:WX_ERROR_DOMAIN
+                                                                     code:((NSHTTPURLResponse *)urlResponse).statusCode
+                                                                 userInfo:@{@"message":@"status code error."}];
+                                
+                                return ;
+                            }
+                            NSString * script = [[NSString alloc] initWithData:totalData encoding:NSUTF8StringEncoding];
+                            scriptLoadFinish(key, script);
+                        }
+                    }];
+    }
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.h b/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.h
new file mode 100644
index 0000000..fccb826
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.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 (Display)
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.m b/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.m
new file mode 100644
index 0000000..1560177
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.m
@@ -0,0 +1,463 @@
+/**
+ * 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+Display.h"
+#import "WXComponent.h"
+#import "WXComponent_internal.h"
+#import "WXLayer.h"
+#import "WXAssert.h"
+#import "WXDisplayQueue.h"
+#import "WXThreadSafeCounter.h"
+
+#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
+
+@implementation WXComponent (Display)
+
+#pragma mark Public
+
+- (void)setNeedsDisplay
+{
+    WXAssertMainThread();
+    
+    if (_compositingChild) {
+        WXComponent *supercomponent = self.supercomponent;
+        while (supercomponent) {
+            if (supercomponent->_composite) {
+                break;
+            }
+            supercomponent = supercomponent.supercomponent;
+        }
+        [supercomponent setNeedsDisplay];
+    } else {
+        [_layer setNeedsDisplay];
+    }
+}
+
+- (WXDisplayBlock)displayBlock
+{
+    WXDisplayBlock displayBlock = ^UIImage *(CGRect bounds, BOOL(^isCancelled)(void)) {
+        if (isCancelled()) {
+            return nil;
+        }
+        
+        if (![self _needsDrawBorder]) {
+            return nil;
+        }
+        
+        return [self _borderImage];
+    };
+    
+    return displayBlock;
+}
+
+- (WXDisplayCompeletionBlock)displayCompeletionBlock
+{
+    return nil;
+}
+
+#pragma mark Private
+
+- (void)_willDisplayLayer:(CALayer *)layer
+{
+    WXAssertMainThread();
+    
+    if (_compositingChild) {
+        // compsiting children need not draw layer
+        return;
+    }
+    
+    CGRect displayBounds = CGRectMake(0, 0, self.calculatedFrame.size.width, self.calculatedFrame.size.height);
+    
+    WXDisplayBlock displayBlock;
+    if (_composite) {
+        displayBlock = [self _compositeDisplayBlock];
+    } else {
+        displayBlock = [self displayBlock];
+    }
+    WXDisplayCompeletionBlock compeletionBlock = [self displayCompeletionBlock];
+    
+    if (!displayBlock) {
+        if (compeletionBlock) {
+            compeletionBlock(layer, NO);
+        }
+        return;
+    }
+    
+    if (_async) {
+        WXThreadSafeCounter *displayCounter = _displayCounter;
+        int32_t displayValue = [displayCounter increase];
+        BOOL (^isCancelled)() = ^BOOL(){
+            return displayValue != displayCounter.value;
+        };
+        
+        [WXDisplayQueue addBlock:^{
+            if (isCancelled()) {
+                if (compeletionBlock) {
+                    dispatch_async(dispatch_get_main_queue(), ^{
+                        compeletionBlock(layer, NO);
+                    });
+                }
+                return;
+            }
+            
+            UIImage *image = displayBlock(displayBounds, isCancelled);
+            
+            dispatch_async(dispatch_get_main_queue(), ^{
+                if (isCancelled()) {
+                    if (compeletionBlock) {
+                        compeletionBlock(layer, NO);
+                    }
+                    return;
+                }
+                
+                layer.contents = (id)(image.CGImage);
+                
+                if (compeletionBlock) {
+                    compeletionBlock(layer, YES);
+                }
+            });
+            
+        }];
+    } else {
+        UIImage *image = displayBlock(displayBounds, ^BOOL(){
+            return NO;
+        });
+        
+        _layer.contents = (id)image.CGImage;
+        
+        if (compeletionBlock) {
+            compeletionBlock(layer, YES);
+        }
+    }
+}
+
+- (WXDisplayBlock)_compositeDisplayBlock
+{
+    return ^UIImage* (CGRect bounds, BOOL(^isCancelled)(void)) {
+        if (isCancelled()) {
+            return nil;
+        }
+        NSMutableArray *displayBlocks = [NSMutableArray array];
+        [self _collectDisplayBlocks:displayBlocks isCancelled:isCancelled];
+        
+        BOOL opaque = _layer.opaque && CGColorGetAlpha(_backgroundColor.CGColor) == 1.0f;
+        
+        UIGraphicsBeginImageContextWithOptions(bounds.size, opaque, 0.0);
+        
+        for (dispatch_block_t block in displayBlocks) {
+            if (isCancelled()) {
+                UIGraphicsEndImageContext();
+                return nil;
+            }
+            block();
+        }
+        
+        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
+        UIGraphicsEndImageContext();
+        
+        return image;
+    };
+}
+
+- (void)_collectDisplayBlocks:(NSMutableArray *)displayBlocks isCancelled:(BOOL(^)(void))isCancelled
+{
+    // compositingChild has no chance to applyPropertiesToView, so force updateNode
+    //    if (_compositingChild) {
+    //        if (_data) {
+    //            dispatch_async(dispatch_get_main_queue(), ^{
+    //                [self updateNode:_data];
+    //            });
+    //        }
+    //    }
+    
+    UIColor *backgroundColor = _backgroundColor;
+    BOOL clipsToBounds = _clipToBounds;
+    CGRect frame = self.calculatedFrame;
+    CGRect bounds = CGRectMake(0, 0, frame.size.width, frame.size.height);
+    
+    if (_composite) {
+        frame.origin = CGPointMake(0, 0);
+    }
+    
+    WXDisplayBlock displayBlock = [self displayBlock];
+    
+    BOOL shouldDisplay = displayBlock || backgroundColor || CGPointEqualToPoint(CGPointZero, frame.origin) == NO || clipsToBounds;
+    
+    if (shouldDisplay) {
+        dispatch_block_t displayBlockToPush = ^{
+            CGContextRef context = UIGraphicsGetCurrentContext();
+            CGContextSaveGState(context);
+            CGContextTranslateCTM(context, frame.origin.x, frame.origin.y);
+            
+            if (_compositingChild && clipsToBounds) {
+                [[UIBezierPath bezierPathWithRect:bounds] addClip];
+            }
+            
+            CGColorRef backgroundCGColor = backgroundColor.CGColor;
+            if (backgroundColor && CGColorGetAlpha(backgroundCGColor) > 0.0) {
+                CGContextSetFillColorWithColor(context, backgroundCGColor);
+                CGContextFillRect(context, bounds);
+            }
+            
+            if (displayBlock) {
+                UIImage *image = displayBlock(bounds, isCancelled);
+                if (image) {
+                    [image drawInRect:bounds];
+                }
+            }
+        };
+        [displayBlocks addObject:[displayBlockToPush copy]];
+    }
+    
+    for (WXComponent *component in self.subcomponents) {
+        if (!isCancelled()) {
+            [component _collectDisplayBlocks:displayBlocks isCancelled:isCancelled];
+        }
+    }
+    
+    if (shouldDisplay) {
+        dispatch_block_t blockToPop = ^{
+            CGContextRef context = UIGraphicsGetCurrentContext();
+            CGContextRestoreGState(context);
+        };
+        [displayBlocks addObject:[blockToPop copy]];
+    }
+}
+
+#pragma mark Border Drawing
+
+- (UIImage *)_borderImage
+{
+    CGSize size = self.calculatedFrame.size;
+    if (size.width <= 0 || size.height <= 0) {
+        return nil;
+    }
+    
+    UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
+    CGContextRef context = UIGraphicsGetCurrentContext();
+    
+    [self _drawBorderWithContext:context size:size];
+    
+    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
+    UIGraphicsEndImageContext();
+    
+    return image;
+}
+
+- (void)_drawBorderWithContext:(CGContextRef)context size:(CGSize)size
+{
+    if (_backgroundColor && CGColorGetAlpha(_backgroundColor.CGColor) > 0) {
+        CGContextSetFillColorWithColor(context, _backgroundColor.CGColor);
+        UIBezierPath *bezierPath = [UIBezierPath bezierPath];
+        [bezierPath moveToPoint:CGPointMake(size.width -_borderTopRightRadius, 0)];
+        [bezierPath addLineToPoint:CGPointMake(_borderTopLeftRadius, 0)];
+        [bezierPath addArcWithCenter:CGPointMake(_borderTopLeftRadius, _borderTopLeftRadius) radius:_borderTopLeftRadius startAngle:M_PI+M_PI_2 endAngle:M_PI clockwise:0];
+        [bezierPath addLineToPoint:CGPointMake(0, size.height-_borderBottomLeftRadius)];
+        [bezierPath addArcWithCenter:CGPointMake(_borderBottomLeftRadius, size.height-_borderBottomLeftRadius) radius:_borderBottomLeftRadius startAngle: M_PI endAngle:M_PI_2 clockwise:0];
+        [bezierPath addLineToPoint:CGPointMake(size.width-_borderBottomRightRadius, size.height)];
+        [bezierPath addArcWithCenter:CGPointMake(size.width-_borderBottomRightRadius, size.height-_borderBottomRightRadius) radius:_borderBottomRightRadius startAngle: M_PI_2 endAngle:0 clockwise:0];
+        [bezierPath addLineToPoint:CGPointMake(size.width, _borderTopRightRadius)];
+        [bezierPath addArcWithCenter:CGPointMake(size.width-_borderTopRightRadius, _borderTopRightRadius) radius:_borderTopRightRadius startAngle: 0 endAngle:-M_PI_2 clockwise:0];
+        [bezierPath fill];
+    }
+    
+    // TOP
+    if (_borderTopWidth > 0) {
+        if(_borderTopStyle == WXBorderStyleDashed || _borderTopStyle == WXBorderStyleDotted){
+            CGFloat lengths[2];
+            lengths[0] = lengths[1] = (_borderTopStyle == WXBorderStyleDashed ? 3 : 1) * _borderTopWidth;
+            CGContextSetLineDash(context, 0, lengths, sizeof(lengths) / sizeof(*lengths));
+        } else{
+            CGContextSetLineDash(context, 0, 0, 0);
+        }
+        CGContextSetLineWidth(context, _borderTopWidth);
+        CGContextSetStrokeColorWithColor(context, _borderTopColor.CGColor);
+        CGContextAddArc(context, size.width-_borderTopRightRadius, _borderTopRightRadius, _borderTopRightRadius-_borderTopWidth/2, -M_PI_4+(_borderRightWidth>0?0:M_PI_4), -M_PI_2, 1);
+        CGContextMoveToPoint(context, size.width-_borderTopRightRadius, _borderTopWidth/2);
+        CGContextAddLineToPoint(context, _borderTopLeftRadius, _borderTopWidth/2);
+        CGContextAddArc(context, _borderTopLeftRadius, _borderTopLeftRadius, _borderTopLeftRadius-_borderTopWidth/2, -M_PI_2, -M_PI_2-M_PI_4-(_borderLeftWidth>0?0:M_PI_4), 1);
+        CGContextStrokePath(context);
+    }
+    
+    // Left
+    if (_borderLeftWidth > 0) {
+        if(_borderLeftStyle == WXBorderStyleDashed || _borderLeftStyle == WXBorderStyleDotted){
+            CGFloat lengths[2];
+            lengths[0] = lengths[1] = (_borderLeftStyle == WXBorderStyleDashed ? 3 : 1) * _borderLeftWidth;
+            CGContextSetLineDash(context, 0, lengths, sizeof(lengths) / sizeof(*lengths));
+        } else{
+            CGContextSetLineDash(context, 0, 0, 0);
+        }
+        CGContextSetLineWidth(context, _borderLeftWidth);
+        CGContextSetStrokeColorWithColor(context, _borderLeftColor.CGColor);
+        CGContextAddArc(context, _borderTopLeftRadius, _borderTopLeftRadius, _borderTopLeftRadius-_borderLeftWidth/2, -M_PI, -M_PI_2-M_PI_4+(_borderTopWidth > 0?0:M_PI_4), 0);
+        CGContextMoveToPoint(context, _borderLeftWidth/2, _borderTopLeftRadius);
+        CGContextAddLineToPoint(context, _borderLeftWidth/2, size.height-_borderBottomLeftRadius);
+        CGContextAddArc(context, _borderBottomLeftRadius, size.height-_borderBottomLeftRadius, _borderBottomLeftRadius-_borderLeftWidth/2, M_PI, M_PI-M_PI_4-(_borderBottomWidth>0?0:M_PI_4), 1);
+        CGContextStrokePath(context);
+    }
+    
+    // Bottom
+    if (_borderBottomWidth > 0) {
+        if(_borderBottomStyle == WXBorderStyleDashed || _borderBottomStyle == WXBorderStyleDotted){
+            CGFloat lengths[2];
+            lengths[0] = lengths[1] = (_borderBottomStyle == WXBorderStyleDashed ? 3 : 1) * _borderBottomWidth;
+            CGContextSetLineDash(context, 0, lengths, sizeof(lengths) / sizeof(*lengths));
+        } else{
+            CGContextSetLineDash(context, 0, 0, 0);
+        }
+        CGContextSetLineWidth(context, _borderBottomWidth);
+        CGContextSetStrokeColorWithColor(context, _borderBottomColor.CGColor);
+        CGContextAddArc(context, _borderBottomLeftRadius, size.height-_borderBottomLeftRadius, _borderBottomLeftRadius-_borderBottomWidth/2, M_PI-M_PI_4+(_borderLeftWidth>0?0:M_PI_4), M_PI_2, 1);
+        CGContextMoveToPoint(context, _borderBottomLeftRadius, size.height-_borderBottomWidth/2);
+        CGContextAddLineToPoint(context, size.width-_borderBottomRightRadius, size.height-_borderBottomWidth/2);
+        CGContextAddArc(context, size.width-_borderBottomRightRadius, size.height-_borderBottomRightRadius, _borderBottomRightRadius-_borderBottomWidth/2, M_PI_2, M_PI_4-(_borderRightWidth > 0?0:M_PI_4), 1);
+        CGContextStrokePath(context);
+    }
+    
+    // Right
+    if (_borderRightWidth > 0) {
+        if(_borderRightStyle == WXBorderStyleDashed || _borderRightStyle == WXBorderStyleDotted){
+            CGFloat lengths[2];
+            lengths[0] = lengths[1] = (_borderRightStyle == WXBorderStyleDashed ? 3 : 1) * _borderRightWidth;
+            CGContextSetLineDash(context, 0, lengths, sizeof(lengths) / sizeof(*lengths));
+        } else{
+            CGContextSetLineDash(context, 0, 0, 0);
+        }
+        CGContextSetLineWidth(context, _borderRightWidth);
+        CGContextSetStrokeColorWithColor(context, _borderRightColor.CGColor);
+        CGContextAddArc(context, size.width-_borderBottomRightRadius, size.height-_borderBottomRightRadius, _borderBottomRightRadius-_borderRightWidth/2, M_PI_4+(_borderBottomWidth>0?0:M_PI_4), 0, 1);
+        CGContextMoveToPoint(context, size.width-_borderRightWidth/2, size.height-_borderBottomRightRadius);
+        CGContextAddLineToPoint(context, size.width-_borderRightWidth/2, _borderTopRightRadius);
+        CGContextAddArc(context, size.width-_borderTopRightRadius, _borderTopRightRadius, _borderTopRightRadius-_borderRightWidth/2, 0, -M_PI_4-(_borderTopWidth > 0?0:M_PI_4), 1);
+        CGContextStrokePath(context);
+    }
+    
+    CGContextStrokePath(context);
+}
+
+- (BOOL)_needsDrawBorder
+{
+    if (![_layer isKindOfClass:[WXLayer class]]) {
+        // Only support WXLayer
+        return NO;
+    }
+    if (_async) {
+        // Async layer always draw border
+        return YES;
+    }
+    if (!(_borderLeftStyle == _borderTopStyle &&
+          _borderTopStyle == _borderRightStyle &&
+          _borderRightStyle == _borderBottomStyle &&
+          _borderBottomStyle == WXBorderStyleSolid)
+        ) {
+        // Native border property doesn't support dashed or dotted border
+        return YES;
+    }
+    
+    // user native border property only when border width & color & radius are equal;
+    BOOL widthEqual = _borderTopWidth == _borderRightWidth && _borderRightWidth == _borderBottomWidth && _borderBottomWidth == _borderLeftWidth;
+    if (!widthEqual) {
+        return YES;
+    }
+    BOOL radiusEqual = _borderTopLeftRadius == _borderTopRightRadius && _borderTopRightRadius == _borderBottomRightRadius && _borderBottomRightRadius == _borderBottomLeftRadius;
+    if (!radiusEqual) {
+        return YES;
+    }
+    BOOL colorEqual = [_borderTopColor isEqual:_borderRightColor] && [_borderRightColor isEqual:_borderBottomColor] && [_borderBottomColor isEqual:_borderLeftColor];
+    if (!colorEqual) {
+        return YES;
+    }
+    
+    return NO;
+}
+
+- (void)_recomputeBorderRadius
+{
+    // prevent overlapping,
+    CGFloat topRadiusScale  = (_borderTopLeftRadius + _borderTopRightRadius == 0) ? 1 : MIN(1, _calculatedFrame.size.width / (_borderTopLeftRadius + _borderTopRightRadius));
+    CGFloat leftRadiusScale = (_borderTopLeftRadius + _borderBottomLeftRadius == 0) ? 1 : MIN(1, _calculatedFrame.size.height / (_borderTopLeftRadius + _borderBottomLeftRadius));
+    CGFloat bottomRadiusScale = (_borderBottomLeftRadius + _borderBottomRightRadius == 0) ? 1 :MIN(1, _calculatedFrame.size.width / (_borderBottomLeftRadius + _borderBottomRightRadius));
+    CGFloat rightRadiusScale = (_borderTopRightRadius+ _borderBottomRightRadius == 0) ? 1 : MIN(1, _calculatedFrame.size.height / (_borderTopRightRadius+ _borderBottomRightRadius));
+    CGFloat finalScale = MIN(MIN(MIN(topRadiusScale, leftRadiusScale), bottomRadiusScale), rightRadiusScale);
+    _borderTopLeftRadius *= finalScale;
+    _borderTopRightRadius *= finalScale;
+    _borderBottomRightRadius *= finalScale;
+    _borderBottomLeftRadius *= finalScale;
+}
+
+- (void)_handleBorders:(NSDictionary *)styles isUpdating:(BOOL)updating
+{
+    if (!updating) {
+        // init with defalut value
+        _borderTopStyle = _borderRightStyle = _borderBottomStyle = _borderLeftStyle = WXBorderStyleSolid;
+        _borderTopColor = _borderLeftColor = _borderRightColor = _borderBottomColor = [UIColor blackColor];
+        _borderTopWidth = _borderLeftWidth = _borderRightWidth = _borderBottomWidth = 0;
+        _borderTopLeftRadius = _borderTopRightRadius = _borderBottomLeftRadius = _borderBottomRightRadius = 0;
+    }
+    
+    BOOL previousNeedsDrawBorder = YES;
+    if (updating) {
+        previousNeedsDrawBorder = [self _needsDrawBorder];
+    }
+    
+#define WX_CHECK_BORDER_PROP(prop, direction1, direction2, direction3, direction4, type, setLayerProp)\
+do {\
+    BOOL needsDisplay = NO; \
+    NSString *styleProp= WX_NSSTRING(WX_CONCAT(border, prop));\
+    if (styles[styleProp]) {\
+        _border##direction1##prop = _border##direction2##prop = _border##direction3##prop = _border##direction4##prop = [WXConvert type:styles[styleProp]];\
+        needsDisplay = YES;\
+    }\
+    NSString *styleDirection1Prop = WX_NSSTRING(WX_CONCAT_TRIPLE(border, direction1, prop));\
+    if (styles[styleDirection1Prop]) {\
+        _border##direction1##prop = [WXConvert type:styles[styleDirection1Prop]];\
+        needsDisplay = YES;\
+    }\
+    NSString *styleDirection2Prop = WX_NSSTRING(WX_CONCAT_TRIPLE(border, direction2, prop));\
+    if (styles[styleDirection2Prop]) {\
+        _border##direction2##prop = [WXConvert type:styles[styleDirection2Prop]];\
+        needsDisplay = YES;\
+    }\
+    NSString *styleDirection3Prop = WX_NSSTRING(WX_CONCAT_TRIPLE(border, direction3, prop));\
+    if (styles[styleDirection3Prop]) {\
+        _border##direction3##prop = [WXConvert type:styles[styleDirection3Prop]];\
+        needsDisplay = YES;\
+    }\
+    NSString *styleDirection4Prop = WX_NSSTRING(WX_CONCAT_TRIPLE(border, direction4, prop));\
+    if (styles[styleDirection4Prop]) {\
+        _border##direction4##prop = [WXConvert type:styles[styleDirection4Prop]];\
+        needsDisplay = YES;\
+    }\
+    if (needsDisplay && updating) {\
+        if (![self _needsDrawBorder]) {\
+            setLayerProp;\
+        }\
+        [self setNeedsDisplay];\
+    }\
+} while (0);
+    
+    WX_CHECK_BORDER_PROP(Style, Top, Left, Bottom, Right, WXBorderStyle,)
+    WX_CHECK_BORDER_PROP(Color, Top, Left, Bottom, Right, UIColor,
+                         _layer.borderColor = _borderTopColor.CGColor)
+    WX_CHECK_BORDER_PROP(Width, Top, Left, Bottom, Right, WXPixelType,
+                         _layer.borderWidth = _borderTopWidth)
+    WX_CHECK_BORDER_PROP(Radius, TopLeft, TopRight, BottomLeft, BottomRight, WXPixelType,
+                         _layer.cornerRadius = _borderTopLeftRadius)
+    
+    if (updating) {
+        BOOL nowNeedsDrawBorder = [self _needsDrawBorder];
+        if (nowNeedsDrawBorder && !previousNeedsDrawBorder) {
+            _layer.cornerRadius = 0;
+            _layer.borderWidth = 0;
+            _layer.backgroundColor = NULL;
+        }
+    }
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Display/WXDisplayQueue.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Display/WXDisplayQueue.h b/ios/sdk/WeexSDK/Sources/Display/WXDisplayQueue.h
new file mode 100644
index 0000000..28fd1c0
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Display/WXDisplayQueue.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>
+
+// Global queue for displaying content
+@interface WXDisplayQueue : NSObject
+
++ (void)addBlock:(void(^)())block;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Display/WXDisplayQueue.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Display/WXDisplayQueue.m b/ios/sdk/WeexSDK/Sources/Display/WXDisplayQueue.m
new file mode 100644
index 0000000..e26b921
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Display/WXDisplayQueue.m
@@ -0,0 +1,45 @@
+/**
+ * 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 "WXDisplayQueue.h"
+
+#define MAX_CONCURRENT_COUNT 8
+
+static dispatch_semaphore_t WXDisplayConcurrentSemaphore;
+
+@implementation WXDisplayQueue
+
++ (dispatch_queue_t)displayQueue
+{
+    static dispatch_queue_t displayQueue = NULL;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        displayQueue = dispatch_queue_create("com.taobao.weex.displayQueue", DISPATCH_QUEUE_CONCURRENT);
+        dispatch_set_target_queue(displayQueue, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0));
+    });
+    
+    return displayQueue;
+}
+
++ (void)addBlock:(void(^)())block
+{
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        NSUInteger processorCount = [NSProcessInfo processInfo].activeProcessorCount;
+        NSUInteger maxConcurrentCount = processorCount <= MAX_CONCURRENT_COUNT ? processorCount : MAX_CONCURRENT_COUNT;
+        WXDisplayConcurrentSemaphore = dispatch_semaphore_create(maxConcurrentCount);
+    });
+    
+    dispatch_async([self displayQueue], ^{
+        dispatch_semaphore_wait(WXDisplayConcurrentSemaphore, DISPATCH_TIME_FOREVER);
+        block();
+        dispatch_semaphore_signal(WXDisplayConcurrentSemaphore);
+    });
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Display/WXLayer.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Display/WXLayer.h b/ios/sdk/WeexSDK/Sources/Display/WXLayer.h
new file mode 100644
index 0000000..6a370b1
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Display/WXLayer.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 <QuartzCore/QuartzCore.h>
+
+@interface WXLayer : CALayer
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Display/WXLayer.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Display/WXLayer.m b/ios/sdk/WeexSDK/Sources/Display/WXLayer.m
new file mode 100644
index 0000000..6929354
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Display/WXLayer.m
@@ -0,0 +1,21 @@
+/**
+ * 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 "WXLayer.h"
+#import "WXDefine.h"
+#import "WXComponent.h"
+#import "WXComponent_internal.h"
+
+@implementation WXLayer
+
+- (void)display
+{
+    [self.wx_component _willDisplayLayer:self];
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.h b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.h
new file mode 100644
index 0000000..0dc2b01
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.h
@@ -0,0 +1,89 @@
+/**
+ * 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 WXSDKEngine : NSObject
+
+/**
+ *  @abstract Registers a module for a given name
+ *
+ *  @param name The module name to register
+ *
+ *  @param clazz  The module class to register
+ *
+ **/
++ (void)registerModule:(NSString *)name withClass:(Class)clazz;
+
+/**
+ * @abstract Registers 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 Registers a component for a given name and specific properties
+ *
+ * @param name The component name to register
+ *
+ * @param clazz The WXComponent subclass to register
+ *
+ * @param properties properties to apply to the component
+ *
+ */
++ (void)registerComponent:(NSString *)name withClass:(Class)clazz withProperties:(NSDictionary *)properties;
+
+/**
+ * @abstract Registers 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 Initializes the global sdk enviroment
+ *
+ * @discussion Injects main.js in app bundle as default JSFramework script.
+ *
+ **/
++ (void)initSDKEnviroment;
+
+/**
+ * @abstract Initializes the enviroment with a given JSFramework script.
+ *
+ **/
++ (void)initSDKEnviroment:(NSString *)script;
+
+/**
+ * @abstract Unloads the bridge context
+ *
+ **/
++ (void)unload;
+
+/**
+ * @abstract Returns the version of SDK
+ *
+ **/
++ (NSString*)SDKEngineVersion;
+
+/**
+ * @abstract Connects to websocket for debugging
+ *
+ * @param URL The URL of websocket to connect
+ *
+ */
++ (void)connectDebugServer:(NSString*)URL;
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/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
new file mode 100644
index 0000000..87738ae
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Engine/WXSDKEngine.m
@@ -0,0 +1,186 @@
+/**
+ * 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 "WXSDKEngine.h"
+#import "WXModuleFactory.h"
+#import "WXHandlerFactory.h"
+#import "WXComponentFactory.h"
+
+#import "WXAppConfiguration.h"
+#import "WXNetworkDefaultImpl.h"
+#import "WXNavigationDefaultImpl.h"
+#import "WXSDKManager.h"
+#import "WXSDKError.h"
+#import "WXSimulatorShortcutMananger.h"
+#import "WXAssert.h"
+#import "WXLog.h"
+#import "WXUtility.h"
+
+@implementation WXSDKEngine
+
+# pragma mark Module Register
+
+// register some default modules when the engine initializes.
++ (void)_registerDefaultModules
+{
+    [self registerModule:@"dom" withClass:NSClassFromString(@"WXDomModule")];
+    [self registerModule:@"navigator" withClass:NSClassFromString(@"WXNavigatorModule")];
+    [self registerModule:@"stream" withClass:NSClassFromString(@"WXStreamModule")];
+    [self registerModule:@"animation" withClass:NSClassFromString(@"WXAnimationModule")];
+    [self registerModule:@"modal" withClass:NSClassFromString(@"WXModalUIModule")];
+    [self registerModule:@"webview" withClass:NSClassFromString(@"WXWebViewModule")];
+    [self registerModule:@"instanceWrap" withClass:NSClassFromString(@"WXInstanceWrap")];
+    [self registerModule:@"timer" withClass:NSClassFromString(@"WXTimerModule")];
+}
+
++ (void)registerModule:(NSString *)name withClass:(Class)clazz
+{
+    WXAssert(name && clazz, @"Fail to register the module, please check if the parameters are correct \uff01");
+    
+    NSString *moduleName = [WXModuleFactory registerModule:name withClass:clazz];
+    NSDictionary *dict = [WXModuleFactory moduleMethodMapsWithName:moduleName];
+    
+    [[WXSDKManager bridgeMgr] registerModules:dict];
+}
+
+# pragma mark Component Register
+
+// register some default components when the engine initializes.
++ (void)_registerDefaultComponents
+{
+    [self registerComponent:@"container" withClass:NSClassFromString(@"WXDivComponent") withProperties:nil];
+    [self registerComponent:@"div" withClass:NSClassFromString(@"WXComponent") withProperties:nil];
+    [self registerComponent:@"text" withClass:NSClassFromString(@"WXTextComponent") withProperties:nil];
+    [self registerComponent:@"image" withClass:NSClassFromString(@"WXImageComponent") withProperties:nil];
+    [self registerComponent:@"scroller" withClass:NSClassFromString(@"WXScrollerComponent") withProperties:nil];
+    [self registerComponent:@"list" withClass:NSClassFromString(@"WXListComponent") withProperties:nil];
+    
+    [self registerComponent:@"cell" withClass:NSClassFromString(@"WXCellComponent")];
+    [self registerComponent:@"embed" withClass:NSClassFromString(@"WXEmbedComponent")];
+    [self registerComponent:@"a" withClass:NSClassFromString(@"WXAComponent")];
+    
+    [self registerComponent:@"select" withClass:NSClassFromString(@"WXSelectComponent")];
+    [self registerComponent:@"switch" withClass:NSClassFromString(@"WXSwitchComponent")];
+    [self registerComponent:@"input" withClass:NSClassFromString(@"WXTextInputComponent")];
+    [self registerComponent:@"video" withClass:NSClassFromString(@"WXVideoComponent")];
+    [self registerComponent:@"indicator" withClass:NSClassFromString(@"WXIndicatorComponent")];
+    [self registerComponent:@"slider" withClass:NSClassFromString(@"WXSliderComponent")];
+    [self registerComponent:@"web" withClass:NSClassFromString(@"WXWebComponent")];
+    [self registerComponent:@"loading" withClass:NSClassFromString(@"WXLoadingComponent")];
+    [self registerComponent:@"loading-indicator" withClass:NSClassFromString(@"WXLoadingIndicator")];
+    [self registerComponent:@"refresh" withClass:NSClassFromString(@"WXRefreshComponent")];
+}
+
++ (void)registerComponent:(NSString *)name withClass:(Class)clazz
+{
+    [self registerComponent:name withClass:clazz withProperties: @{@"append":@"tree"}];
+}
+
++ (void)registerComponent:(NSString *)name withClass:(Class)clazz withProperties:(NSDictionary *)properties
+{
+    if (!name || !clazz) {
+        return;
+    }
+    
+    WXAssert(name && clazz, @"Fail to register the component, please check if the parameters are correct \uff01");
+    
+    [WXComponentFactory registerComponent:name withClass:clazz];
+    
+    if (properties) {
+        NSMutableDictionary *props = [properties mutableCopy];
+        props[@"type"] = name;
+        [[WXSDKManager bridgeMgr] registerComponents:@[props]];
+    } else {
+        [[WXSDKManager bridgeMgr] registerComponents:@[name]];
+    }
+}
+
+# pragma mark Handler Register
+
+// register some default handlers when the engine initializes.
++ (void)_registerDefaultHandlers
+{
+    [self registerHandler:[WXNetworkDefaultImpl new] withProtocol:@protocol(WXNetworkProtocol)];
+    [self registerHandler:[WXNavigationDefaultImpl new] withProtocol:@protocol(WXNavigationProtocol)];
+}
+
++ (void)registerHandler:(id)handler withProtocol:(Protocol *)protocol
+{
+    WXAssert(handler && protocol, @"Fail to register the handler, please check if the parameters are correct \uff01");
+    
+    [WXHandlerFactory registerHandler:handler withProtocol:protocol];
+}
+
+# pragma mark SDK Initialize
+
++ (void)initSDKEnviroment
+{
+    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"main" ofType:@"js"];
+    NSString *script = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
+    [WXSDKEngine initSDKEnviroment:script];
+    
+#if TARGET_OS_SIMULATOR
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        [WXSimulatorShortcutMananger registerSimulatorShortcutWithKey:@"i" modifierFlags:UIKeyModifierCommand | UIKeyModifierAlternate action:^{
+            NSURL *URL = [NSURL URLWithString:@"http://localhost:8687/launchDebugger"];
+            NSURLRequest *request = [NSURLRequest requestWithURL:URL];
+            
+            NSURLSession *session = [NSURLSession sharedSession];
+            NSURLSessionDataTask *task = [session dataTaskWithRequest:request
+                                                    completionHandler:
+                                          ^(NSData *data, NSURLResponse *response, NSError *error) {
+                                              // ...
+                                          }];
+            
+            [task resume];
+            WXLogInfo(@"Launching browser...");
+            
+            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+                [self connectDebugServer:@"ws://localhost:8687/debugger/0/renderer"];
+            });
+            
+        }];
+    });
+#endif
+}
+
++ (void)initSDKEnviroment:(NSString *)script
+{
+    if (!script || script.length <= 0) {
+        [WXSDKError monitorAlarm:NO errorCode:WX_ERR_LOAD_JSLIB msg:@"framework loading is failure!"];
+        return;
+    }
+    
+    [self _registerDefaultComponents];
+    [self _registerDefaultModules];
+    [self _registerDefaultHandlers];
+    
+    [[WXSDKManager bridgeMgr] executeJsFramework:script];
+    
+    [WXUtility addStatTrack:[WXAppConfiguration appName]];
+}
+
++ (NSString*)SDKEngineVersion
+{
+    return WX_SDK_VERSION;
+}
+
+# pragma mark Debug
+
++ (void)unload
+{
+    [[WXSDKManager bridgeMgr] unload];
+}
+
++ (void)connectDebugServer:(NSString*)URL
+{
+    [[WXSDKManager bridgeMgr] connectToWebSocket:[NSURL URLWithString:URL]];
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.h b/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.h
new file mode 100644
index 0000000..c9831f6
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.h
@@ -0,0 +1,45 @@
+/**
+ * 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 "WXSDkInstance.h"
+
+extern NSString* const kMonitorAlarmJsBridge;
+extern NSString* const kMonitorAlarmDomModule;
+
+typedef NS_ENUM(int, WXSDKErrCode)
+{
+    WX_ERR_JSBRIAGE_START = -2001,
+    WX_ERR_LOAD_JSLIB = -2002,
+//    WX_ERR_OBJECT_JSON = -2008,
+    WX_ERR_JSFUNC_PARAM = -2009,
+    WA_ERR_INVOKE_NATIVE = -2012,
+    WX_ERR_JS_EXECUTE = -2013,
+    WX_ERR_JSBRIAGE_END = -2099,
+    
+    WX_ERROR_DOMMODULE_START = -2100,
+    WX_ERR_DOM_CREATEBODY = -2100,
+    WX_ERR_DOM_UPDATTR = -2101,
+    WX_ERR_DOM_UPDSTYLE = -2102,
+    WX_ERR_DOM_ADDELEMENT = -2103,
+    WX_ERR_DOM_REMOVEELEMENT = -2104,
+    WX_ERR_DOM_MOVEELEMENT = -2105,
+    WX_ERR_DOM_ADDEVENT = -2106,
+    WX_ERR_DOM_REMOVEEVENT = -2107,
+//    WX_ERR_DOM_CREATEFINISH = -2108,
+//    WX_ERR_DOM_RENDERFINISH = -2109,
+    WX_ERR_DOM_SCROLLTOELEMENT = -2110,
+    WX_ERROR_DOMMODULE_END = -2199,
+};
+
+@interface WXSDKError : NSObject
+
++ (void)monitorAlarm:(BOOL)success errorCode:(WXSDKErrCode)errorCode msg:(NSString *)format, ... NS_FORMAT_FUNCTION(3,4);
+
++ (void) monitorAlarm:(BOOL)success errorCode:(WXSDKErrCode)errorCode errorMessage:(NSString *)message withURL:(NSURL *)url;
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.m b/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.m
new file mode 100644
index 0000000..7f5dc9a
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Engine/WXSDKError.m
@@ -0,0 +1,63 @@
+/**
+ * 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 "WXSDKError.h"
+#import "WXAppMonitorProtocol.h"
+#import "WXHandlerFactory.h"
+#import "WXLog.h"
+
+NSString * const kMonitorAlarmJsBridge = @"jsBridge";
+NSString * const kMonitorAlarmDomModule = @"domModule";
+
+@implementation WXSDKError
+
++ (void)monitorAlarm:(BOOL)success errorCode:(WXSDKErrCode)errorCode msg:(NSString *)format, ... NS_FORMAT_FUNCTION(3,4)
+{
+    if (success) return;
+    
+    va_list args;
+    va_start(args, format);
+    NSString *errorMsg = [[NSString alloc] initWithFormat:format arguments:args];
+    va_end(args);
+    
+    [self monitorAlarm:success errorCode:errorCode errorMessage:errorMsg withURL:nil];
+}
+
++ (void)monitorAlarm:(BOOL)success errorCode:(WXSDKErrCode)errorCode errorMessage:(NSString *)errorMsg withURL:(NSURL *)url
+{
+    if (success) {
+        return;
+    }
+    
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+        if (!success) {
+            WXLogError(@"%@", errorMsg);
+        }
+        
+        id<WXAppMonitorProtocol> appMonitorHandler = [WXHandlerFactory handlerForProtocol:@protocol(WXAppMonitorProtocol)];
+        if ([appMonitorHandler respondsToSelector:@selector(commitAppMonitorAlarm:monitorPoint:success:errorCode:errorMsg:arg:)]) {
+            NSString *pointKey = nil;
+            if (errorCode <= WX_ERR_JSBRIAGE_START &&
+                errorCode >= WX_ERR_JSBRIAGE_END) {
+                pointKey = kMonitorAlarmJsBridge;
+            }
+            else if (errorCode <= WX_ERROR_DOMMODULE_START &&
+                     errorCode >= WX_ERROR_DOMMODULE_END) {
+                pointKey = kMonitorAlarmDomModule;
+            } else {
+                WXLogError(@"");
+            }
+            
+            NSString *errorCodeStr = [NSString stringWithFormat:@"%d", errorCode];
+
+            [appMonitorHandler commitAppMonitorAlarm:@"weex" monitorPoint:pointKey success:success errorCode:errorCodeStr errorMsg:errorMsg arg:@""];
+        }
+    });
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/185fe55c/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.h
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.h b/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.h
new file mode 100644
index 0000000..11d2c88
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.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 "WXComponent.h"
+
+@interface WXComponent (Events) <UIGestureRecognizerDelegate>
+
+@end