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