IOS 原生界面和Weex容器互相跳转实践 附部分js和原生代码

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);
    }
}

猜你喜欢

转载自blog.csdn.net/robinson_911/article/details/83028452