全部产品
云市场
云游戏

iOS Weex容器指南

更新时间:2019-01-14 16:08:28

EMAS-WEEX使用指南

EMAS-WEEX是EMAS官方提供的Weex基础库,提供对Weex官方sdk的实用封装以及各种实用、通用组件,目的在于降低EMAS用户对于Weex的接入、使用成本。

在以上章节 https://help.aliyun.com/document_detail/88331.html 中,EMAS-WEEX做了相应的依赖和初始化操作,这里讲解一些开发过程中使用EMAS-WEEX的使用要点,推荐用户使用EMAS-WEEX而不是Weex官方sdk。

通用渲染层

WeexSDK渲染相关的逻辑统一放在EMASWXViewController中,该ViewController属于渲染容器,还需要业务方提供宿主容器EMASHostViewControllerEMASWXViewController通过addChildViewController方法添加到宿主容器中,使用这种方式,可以将渲染容器和宿主容器解耦,同时不失宿主容器自身的平台特性。

业务方可以继承EMASWXViewController,对渲染过程自定义:

  1. //.h
  2. @interface EMASWXRenderViewController : EMASWXViewController
  3. @end
  4. //.m
  5. @implementation EMASWXRenderViewController
  6. //获取宿主容器的导航控制器。由于当前渲染容器是通过addChildViewController的方式添加到宿主容器中,因此所属的导航控制器应该是通过宿主容器获取。
  7. - (UIViewController *)wxNavigationController {
  8. if (self.parentVC) {
  9. return self.parentVC.navigationController;
  10. }
  11. return nil;
  12. }
  13. //获取渲染容器包含的子视图控制器。例如,web对应的component,它会生成webviewController,并通过addChileViewController的方式添加到渲染容器中。
  14. - (NSMutableArray *)wxChildViewControllers {
  15. return (NSMutableArray *)self.childViewControllers;
  16. }
  17. //在渲染容器中添加特定的子视图控制器。
  18. - (void)wxAddChildViewController:(UIViewController *)viewController {
  19. [self addChildViewController:viewController];
  20. }
  21. //在渲染容器中移除特定的子视图控制器。
  22. - (void)wxRemoveChildViewController:(UIViewController *)viewController {
  23. [viewController removeFromParentViewController];
  24. }
  25. //判断宿主容器导航栏是否隐藏
  26. - (BOOL)wxNavbarIsHidden {
  27. EMASWXViewController *parentVC = (EMASWXViewController *)self.parentVC;
  28. if (parentVC && parentVC.navigationController.navigationBarHidden) {
  29. return YES;
  30. }
  31. return NO;
  32. }
  33. //自定义页面加载的indicatorView,并显示在view中。
  34. - (void)wxShowPageLoadingIndicator:(UIView *)view {
  35. [view addSubview:self.pageLoadingIndicator];
  36. [self.pageLoadingIndicator startAnimating];}
  37. //隐藏indicatorView
  38. - (void)wxHidePageLoadingIndicator {
  39. [self.pageLoadingIndicator stopAnimating];
  40. [self.pageLoadingIndicator removeFromSuperview];
  41. }
  42. - (UIActivityIndicatorView *)pageLoadingIndicator {
  43. if (_pageLoadingIndicator == nil) {
  44. self.pageLoadingIndicator = [[UIActivityIndicatorView alloc]initWithFrame:CGRectMake((self.view.frame.size.width - 40)/2, (self.view.frame.size.height - 40)/2, 40, 40)];
  45. [self.pageLoadingIndicator setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleGray];
  46. }
  47. return _pageLoadingIndicator;
  48. }
  49. - (void)wxInstanceRenderOnCreate {
  50. // Weex渲染容器在实渲染中判断当前实例是否可以被复用
  51. }
  52. - (void)wxInstanceRenderOnFail:(NSError *)error {
  53. // Weex实例渲染失败回调,返回错误信息
  54. }
  55. - (void)wxInstanceRenderOnFinish {
  56. // Weex实例渲染完成回调
  57. }
  58. - (void)wxJSBundleDownloadOnFinish:(WXResourceResponse *)response request:(WXResourceRequest *)request data:(NSData *)data error:(NSError *)error {
  59. // JS Bundle下载回调
  60. }
  61. @end

业务方提供宿主容器EMASHostViewController ,继承自UIViewController或者UINavigationController

  1. //.h
  2. //宿主容器
  3. @interface EMASHostViewController : UIViewController <EMASWXViewControllerProtocol,SRWebSocketDelegate>
  4. @property (nonatomic, strong) SRWebSocket *hotReloadSocket;
  5. @property (nonatomic, copy) NSString *source;
  6. @property(nonatomic, strong) EMASWXRenderViewController *wxViewController;
  7. - (id)initWithNavigatorURL:(NSURL *)URL;
  8. @end
  9. //.m
  10. @interface EMASHostViewController()
  11. @property (nonatomic, copy) NSString *resourceUrlString;
  12. @property (nonatomic, strong) UIWebView *webView;
  13. @end
  14. @implementation EMASHostViewController
  15. - (void)dealloc {
  16. if (self.wxViewController) {
  17. [self.wxViewController removeFromParentViewController];
  18. }
  19. }
  20. - (instancetype)init {
  21. self = [super init];
  22. if (self) {
  23. self = [self initWithNavigatorURL:[NSURL URLWithString:@""]];
  24. }
  25. return self;
  26. }
  27. - (instancetype)initWithNavigatorURL:(NSURL *)URL {
  28. self = [super init];
  29. if (self) {
  30. self.resourceUrlString = URL.absoluteString;
  31. NSString * urlString = self.resourceUrlString;//[[DynamicConfigurationManager sharedInstance] redirectUrl:[URL absoluteString]];
  32. self.wxViewController = [[EMASWXRenderViewController alloc] initWithNavigatorURL:[NSURL URLWithString:urlString] withCustomOptions:@{@"bundleUrl":urlString} withInitData:nil withViewController:self];
  33. //渲染容器的外部代理。
  34. self.wxViewController.delegate = self;
  35. }
  36. return self;
  37. }
  38. - (void)viewDidLoad {
  39. [super viewDidLoad];
  40. [self setupNaviBar];
  41. //务必设置这个属性,它与导航栏隐藏属性相关。
  42. self.edgesForExtendedLayout = UIRectEdgeNone;
  43. //在宿主容器中添加渲染容器和视图。
  44. [self.view addSubview:self.wxViewController.view];
  45. [self addChildViewController:self.wxViewController];
  46. self.view.backgroundColor = [UIColor whiteColor];
  47. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationRefreshInstance:) name:@"RefreshInstance" object:nil];
  48. }
  49. # pragma mark WXViewController Delegate
  50. //内存报警时销毁非当前实例, 是否销毁通过配置下发。
  51. - (void)wxDidReceiveMemoryWarning {
  52. id weex_memory_warning_destroy = @"1";
  53. if (weex_memory_warning_destroy && [@"1" isEqualToString:weex_memory_warning_destroy]) {
  54. if (self.wxViewController.isViewLoaded && [self.view window] == nil ) {
  55. [self.wxViewController.instance destroyInstance];
  56. self.wxViewController.instance = nil;
  57. }
  58. }
  59. }
  60. - (void)wxFinishCreateInstance {
  61. //Weex Instance创建成功
  62. [self.webView removeFromSuperview];
  63. }
  64. - (void)wxFailCreateInstance:(NSError *)error {
  65. //Weex Instance创建失败
  66. }
  67. - (void)wxFinishRenderInstance {
  68. //Weex Instance渲染完成
  69. }
  70. - (void)wxDegradeToH5:(NSString *)url
  71. {
  72. [self.wxViewController.instance destroyInstance];
  73. [self.wxViewController.weexView removeFromSuperview];
  74. [self.webView removeFromSuperview];
  75. self.webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
  76. [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
  77. [self.view addSubview:self.webView];
  78. }
  79. #pragma mark - websocket
  80. - (void)webSocketDidOpen:(SRWebSocket *)webSocket
  81. {
  82. }
  83. - (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message
  84. {
  85. if ([@"refresh" isEqualToString:message]) {
  86. [self.wxViewController refreshWeex];
  87. }
  88. }
  89. - (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error
  90. {
  91. }
  92. #pragma mark - notification
  93. - (void)notificationRefreshInstance:(NSNotification *)notification {
  94. [self.wxViewController refreshWeex];
  95. }
  96. @end

降级

实现EMASWXViewControllerProtocol的代理方法wxDegradeToH5:即可完成weex->h5的降级,

线上url需要满足如下形式

  1. http://cdn.emas-poc.com/material/yanpeicpf/index.html?_wx_tpl=http://cdn.emas-poc.com/app/yanpeicpf-bbb/pages/index/entry.js

_wx_tpl标记后是需要渲染的weex脚本地址(后缀名js/wx等都可以),_wx_tpl标记前是发生错误时需要降级到的H5地址。

protocol默认实现handler说明

protocol Note
WXAppMonitorProtocol 使用了UserTrack库,用于埋点
WXImgLoaderProtocol 使用了 SDWebImage库,用于图片下载
WXResourceRequestHandler 基于 NSURLSession ,处理网络请求,缓存使用了ZCache(基于mtop)
WXJSExceptionProtocol 基于 MotuReport ,上报jsexception