IOS 原生介面和Weex容器互相跳轉實踐 附部分js和原生程式碼
阿新 • • 發佈:2018-11-04
weex相關原理,請看官方網站
此IOS Weex demo實現的功能,從原生介面跳轉到Weex容器頁面,然後點選Weex容器頁面的button(js)跳轉到另一個原生介面。
一. 先上效果圖
二.實現
1. weex容器渲染的js程式碼如下,上面第二張圖的程式碼
啟動一個本地的Node環境,可以通過瀏覽器訪問,也可以通過Weex容器渲染成上面的第二張圖的介面
import { createElement, Component } from 'rax'; import View from 'rax-view'; import Text from 'rax-text'; import Button from 'rax-button'; import { setTitle, openUrl, getAppStoken } from 'lib/jsbridge'; import styles from './app.css'; class APP extends Component { constructor(props) { super(props); this.state = { timesPressed1: 0, list: [], }; } componentDidMount() { // alert('請求錯誤'); // eslint-disable-line } handlePress = () => { this.setState({ timesPressed1: this.state.timesPressed1 + 1, }); // alert('彈框測試!!!'); // eslint-disable-line openUrl({ // url: 'weex://go/scan', url: 'weex://go/ljDetail?orderId=123', }); }; render() { return ( <View style={styles.body}> <Text style={styles.loadingText}>當前頁面是個weex容器</Text> <Text style={styles.loadingText}>載入的是個weex頁面</Text> <Button style={styles.button} onPress={this.handlePress}>點選我從weex頁面跳轉到原生</Button> </View> ); } } export default APP;
2. 原生的Weex容器
NSString *url = @"http://10.50.62.53:9999/wxTest/index.html?lj_weexurl=http://10.50.62.53:9999/wxTest/index.js";
此容器的設計,當Weex載入失敗的時候,可以將當前的展示成html頁面,載入的是wxTest/index.html頁面,不影響使用。
當Weex載入成功的時候,渲染的是wxTest/index.js的程式碼
#import "WXViewController.h" #import <WeexSDK/WXSDKInstance.h> #import <WeexSDK/WXSDKEngine.h> #import <WeexSDK/WXUtility.h> #import <WeexSDK/WXDebugTool.h> #import <WeexSDK/WXSDKManager.h> #import "UIViewController+WXDemoNaviBar.h" #import "WXPrerenderManager.h" #import "WXMonitor.h" #import "WXTracingManager.h" #import "LJWKWebView.h" #import "LJWKWebViewUtils.h" #define kNavAndStatuesHeight 64 #define kUseWeexFlag @"lj_weexurl" @interface WXViewController () @property (nonatomic, strong) WXSDKInstance *instance; @property (nonatomic, strong) UIView *weexView; @property (nonatomic, assign) BOOL isUseWeexRender; //是否使用weex渲染 @property (nonatomic, strong) LJWKWebView *webView; @end @implementation WXViewController #pragma mark -- dealloc - (void)dealloc { [_instance destroyInstance]; [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (instancetype)init { self = [super init]; if (self) { NSAssert(NO, @"請使用initWithUrl初始化"); } return self; } - (instancetype)initWithUrl:(NSURL *)url useWeexEnv:(BOOL)useWeexEnv { self = [super init]; if (self) { _url = url; _isUseWeexRender = useWeexEnv && ([url.absoluteString rangeOfString:kUseWeexFlag].location != NSNotFound); } return self; } #pragma mark -- life cycle - (void)viewDidLoad { [super viewDidLoad]; // [self setTopNavBarTitle:@"Weex Container"]; [self setGrayTopBarBg]; if (_isUseWeexRender) { [self.view setClipsToBounds:YES]; [self renderWeex]; }else{ [self setDeafaultTopBarBg]; [self setTopNavBackButton]; [self setTopNavBarTitle:@"載入中..."]; [self loadWebViewWithUrl:self.url.absoluteString]; } } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; if (_isUseWeexRender) { [self updateInstanceState:WeexInstanceAppear]; } } - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; if (_isUseWeexRender) { [self updateInstanceState:WeexInstanceDisappear]; } }
appdelegate程式碼
#import "AppDelegate.h" #import "WXViewController.h" #import "UIViewController+WXDemoNaviBar.h" #import "WXLJCustomeEventModule.h" #import "WXImgLoaderDefaultImpl.h" #import "WXScannerVC.h" #import "UIView+UIThreadCheck.h" #import <WeexSDK/WeexSDK.h> #import <AVFoundation/AVFoundation.h> #import <ATSDK/ATManager.h> #import "WXNavigationHandlerImpl.h" #import "ViewController.h" //#import "WXAnalyzerCenter.h" #ifdef DEBUG #import "DebugAnalyzer.h" #endif @interface AppDelegate () @end @implementation AppDelegate #pragma mark #pragma mark application - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; self.window.backgroundColor = [UIColor whiteColor]; [self initWeexSDK]; ViewController *vc = [[ViewController alloc]init]; UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:vc]; self.window.rootViewController = nav; [self.window makeKeyAndVisible]; [self startSplashScreen]; #if DEBUG // check if there are any UI changes on main thread. [UIView wx_checkUIThread]; #endif return YES; } - (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler { if ([shortcutItem.type isEqualToString:QRSCAN]) { WXScannerVC * scanViewController = [[WXScannerVC alloc] init]; [(WXRootViewController*)self.window.rootViewController pushViewController:scanViewController animated:YES]; } if ([shortcutItem.type isEqualToString:QRSCAN_HISTORY]) { // WXScannerHistoryVC *scannerHistoryVC = [WXScannerHistoryVC new]; // [(WXRootViewController*)self.window.rootViewController pushViewController:scannerHistoryVC animated:YES]; } } - (void)applicationDidEnterBackground:(UIApplication *)application { #ifdef UITEST #if !TARGET_IPHONE_SIMULATOR NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; setenv("GCOV_PREFIX", [documentsDirectory cStringUsingEncoding:NSUTF8StringEncoding], 1); setenv("GCOV_PREFIX_STRIP", "6", 1); #endif extern void __gcov_flush(void); __gcov_flush(); #endif } - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url { NSString *newUrlStr = url.absoluteString; if([url.scheme isEqualToString:@"wxpage"]) { newUrlStr = [newUrlStr stringByReplacingOccurrencesOfString:@"wxpage://" withString:@"http://"]; } UIViewController * viewController = [self demoController:newUrlStr]; // ((WXViewController*)viewController).url = [NSURL URLWithString:newUrlStr]; [(WXRootViewController*)self.window.rootViewController pushViewController:viewController animated:YES]; return YES; } #pragma mark weex - (void)initWeexSDK { [WXAppConfiguration setAppGroup:@"AliApp"]; [WXAppConfiguration setAppName:@"WeexDemo"]; [WXAppConfiguration setExternalUserAgent:@"ExternalUA"]; [WXSDKEngine initSDKEnvironment]; [WXSDKEngine registerHandler:[WXImgLoaderDefaultImpl new] withProtocol:@protocol(WXImgLoaderProtocol)]; [WXSDKEngine registerHandler:[WXNavigationHandlerImpl new] withProtocol:@protocol(WXNavigationProtocol)]; // 註冊自定義的JS回撥原生方法的事件方法 [WXSDKEngine registerHandler:[WXLJCustomeEventModule new] withProtocol:@protocol(WXModuleProtocol)]; [WXSDKEngine registerModule:@"actionBridge" withClass:[WXLJCustomeEventModule class]]; // 註冊自定義的JS回撥原生方法的事件方法 #ifdef DEBUG [WXAnalyzerCenter addWxAnalyzer:[DebugAnalyzer new]]; #endif #if !(TARGET_IPHONE_SIMULATOR) [self checkUpdate]; #endif #ifdef DEBUG [self atAddPlugin]; [WXDebugTool setDebug:YES]; [WXLog setLogLevel:WXLogLevelLog]; #ifndef UITEST [[ATManager shareInstance] show]; #endif #else [WXDebugTool setDebug:NO]; [WXLog setLogLevel:WXLogLevelError]; #endif } - (UIViewController *)demoController:(NSString*)url { // NSString *url = @"http://10.50.62.53:9999/wxTest/index.js"; // NSString *url = @"http://10.50.62.53:9999/wxTableview/index.js"; // NSString *url = @"https://www.baidu.com/"; UIViewController *demo = [[WXViewController alloc] initWithUrl:[NSURL URLWithString:url] useWeexEnv:YES]; return demo; } #pragma mark #pragma mark animation when startup - (void)startSplashScreen { UIView* splashView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; splashView.backgroundColor = WEEX_COLOR; UIImageView *iconImageView = [UIImageView new]; UIImage *icon = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"weex-icon" ofType:@"png"]]; if ([icon respondsToSelector:@selector(imageWithRenderingMode:)]) { iconImageView.image = [icon imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; iconImageView.tintColor = [UIColor whiteColor]; } else { iconImageView.image = icon; } iconImageView.frame = CGRectMake(0, 0, 320, 320); iconImageView.contentMode = UIViewContentModeScaleAspectFit; iconImageView.center = splashView.center; [splashView addSubview:iconImageView]; [self.window addSubview:splashView]; float animationDuration = 1.4; CGFloat shrinkDuration = animationDuration * 0.3; CGFloat growDuration = animationDuration * 0.7; if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) { [UIView animateWithDuration:shrinkDuration delay:1.0 usingSpringWithDamping:0.7f initialSpringVelocity:10 options:UIViewAnimationOptionCurveEaseInOut animations:^{ CGAffineTransform scaleTransform = CGAffineTransformMakeScale(0.75, 0.75); iconImageView.transform = scaleTransform; } completion:^(BOOL finished) { [UIView animateWithDuration:growDuration animations:^{ CGAffineTransform scaleTransform = CGAffineTransformMakeScale(20, 20); iconImageView.transform = scaleTransform; splashView.alpha = 0; } completion:^(BOOL finished) { [splashView removeFromSuperview]; }]; }]; } else { [UIView animateWithDuration:shrinkDuration delay:1.0 options:0 animations:^{ CGAffineTransform scaleTransform = CGAffineTransformMakeScale(0.75, 0.75); iconImageView.transform = scaleTransform; } completion:^(BOOL finished) { [UIView animateWithDuration:growDuration animations:^{ CGAffineTransform scaleTransform = CGAffineTransformMakeScale(20, 20); iconImageView.transform = scaleTransform; splashView.alpha = 0; } completion:^(BOOL finished) { [splashView removeFromSuperview]; }]; }]; } } #pragma mark - (void)atAddPlugin { #if DEBUG [[ATManager shareInstance] addPluginWithId:@"weex" andName:@"weex" andIconName:@"../weex" andEntry:@"" andArgs:@[@""]]; [[ATManager shareInstance] addSubPluginWithParentId:@"weex" andSubId:@"logger" andName:@"logger" andIconName:@"log" andEntry:@"WXATLoggerPlugin" andArgs:@[@""]]; // [[ATManager shareInstance] addSubPluginWithParentId:@"weex" andSubId:@"viewHierarchy" andName:@"hierarchy" andIconName:@"log" andEntry:@"WXATViewHierarchyPlugin" andArgs:@[@""]]; [[ATManager shareInstance] addSubPluginWithParentId:@"weex" andSubId:@"test2" andName:@"test" andIconName:@"at_arr_refresh" andEntry:@"" andArgs:@[]]; [[ATManager shareInstance] addSubPluginWithParentId:@"weex" andSubId:@"test3" andName:@"test" andIconName:@"at_arr_refresh" andEntry:@"" andArgs:@[]]; #endif } - (void)checkUpdate { __weak typeof(self) weakSelf = self; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSDictionary *infoDic = [[NSBundle mainBundle] infoDictionary]; NSString *currentVersion = [infoDic objectForKey:@"CFBundleShortVersionString"]; NSString *URL = @"http://itunes.apple.com/lookup?id=1130862662"; NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; [request setURL:[NSURL URLWithString:URL]]; [request setHTTPMethod:@"POST"]; NSHTTPURLResponse *urlResponse = nil; NSError *error = nil; NSData *recervedData = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&error]; NSString *results = [[NSString alloc] initWithBytes:[recervedData bytes] length:[recervedData length] encoding:NSUTF8StringEncoding]; NSDictionary *dic = [WXUtility objectFromJSON:results]; NSArray *infoArray = [dic objectForKey:@"results"]; if ([infoArray count]) { NSDictionary *releaseInfo = [infoArray objectAtIndex:0]; weakSelf.latestVer = [releaseInfo objectForKey:@"version"]; if ([weakSelf.latestVer floatValue] > [currentVersion floatValue]) { if (![[NSUserDefaults standardUserDefaults] boolForKey: weakSelf.latestVer]) { [[NSUserDefaults standardUserDefaults] setBool:FALSE forKey:weakSelf.latestVer]; dispatch_async(dispatch_get_main_queue(), ^{ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"New Version" message:@"Will update to a new version" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"update", nil]; [alert show]; }); } } } }); } - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { switch (buttonIndex) { case 0: [[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:self.latestVer]; break; case 1: [[UIApplication sharedApplication]openURL:[NSURL URLWithString:@"itms-apps://itunes.apple.com/cn/app/weex-playground/id1130862662?mt=8"]]; default: break; } [alertView dismissWithClickedButtonIndex:buttonIndex animated:YES]; } @end
自定義的weex元件-------具體跟js互動的檔案
#import "WXLJCustomeEventModule.h"
#import <WeexSDK/WeexSDK.h>
#import "WXViewController.h"
#import "HomeViewController.h"
@interface WXLJCustomeEventModule()
@property (nonatomic, copy) WXModuleKeepAliveCallback loginSuccessCallBack;
@end
@implementation WXLJCustomeEventModule
@synthesize weexInstance;
WX_EXPORT_METHOD(@selector(openUrl:callback:))
WX_EXPORT_METHOD(@selector(close:callback:))
WX_EXPORT_METHOD(@selector(setNavBarTitle:callback:))
- (void)openUrl:(id)paramsJSON callback:(WXModuleKeepAliveCallback)callback
{
NSDictionary *paramsDic = [CHUtil dictionaryWithJsonString:paramsJSON];
// url: 'weex://go/ljDetail?orderId=123',
if (paramsDic) {
NSString *url = paramsDic[@"url"];
NSDictionary *queryDic = [CHUtil getParamsDicWithUrl: url];
if ([url hasPrefix:@"http"]) {
WXViewController *vc = [[WXViewController alloc] initWithUrl:[NSURL URLWithString:url] useWeexEnv:YES];
[[weexInstance.viewController navigationController] pushViewController:vc animated:YES];
} else if ([url hasPrefix:@"weex"] && [url rangeOfString:@"ljDetail"].location != NSNotFound){
HomeViewController *vc = [HomeViewController new ];
vc.orderId = queryDic[@"orderId"];
[[weexInstance.viewController navigationController] pushViewController:vc animated:YES];
NSLog(@"url:%@", url);
return;
}
}
}
- (void)close:(id)paramsJSON callback:(WXModuleKeepAliveCallback)callback
{
[weexInstance.viewController.navigationController popViewControllerAnimated:YES];
if (callback) {
callback(@"", NO);
}
}