博主学习weex也有一段日子了,以前写的Demo都是属于纯weex的,最多就是把所有的js文件引入Xcode项目中,通过加载本地的js文件的方式来实现项目,但也仅仅只存在一个VC,相当于是内嵌了网页的app,当然,weex的性能要好很多。
那么接下来,博主将向大家展示怎么通过weex的js文件实现不同的VC之间的交互,以及Xcode和weex的交互:
1.自定义module,实现push方法(在这样的项目环境,navagator肯定是不能用的)
#import <Foundation/Foundation.h> #import <WeexSDK/WeexSDK.h> @interface WXEventModule : NSObject <WXModuleProtocol> @end #import "WXEventModule.h" #import "HomeBigViewController.h" @implementation WXEventModule @synthesize weexInstance; WX_EXPORT_METHOD(@selector(push:)) //WX_EXPORT_METHOD(@selector(pop)) //WX_EXPORT_METHOD(@selector(present:)) //WX_EXPORT_METHOD(@selector(dismiss)) // //WX_EXPORT_METHOD(@selector(postGlobalEvent::)) - (void)anotherOpenURL:(NSString *)url callback:(WXKeepAliveCallback)callback { callback(url,false); NSLog(@"call me"); } - (void)openURL:(NSString *)url { NSString *newURL = url; if ([url hasPrefix:@"//"]) { newURL = [NSString stringWithFormat:@"http:%@", url]; } else if (![url hasPrefix:@"http"]) { // relative path newURL = [NSURL URLWithString:url relativeToURL:weexInstance.scriptURL].absoluteString; } UIViewController *controller = [[HomeBigViewController alloc] init]; ((HomeBigViewController *)controller).url = [NSURL URLWithString:newURL]; [[weexInstance.viewController navigationController] pushViewController:controller animated:YES]; } - (void)push:(NSString *)url { [self openURL:url]; }
2.如上,push方法已经定义完毕,你可以在weex里面来直接使用了,但是在此之前需要在Xcode的Appdelegate中注册module:
//第一个名字你可以随便取,总之用的时候需要一样,后面的类名要和类名一致 [WXSDKEngine registerModule:@"WXEventModule" withClass:NSClassFromString(@"WXEventModule")];
3.如何在weex中使用这个push方法
//这是weex里的一个方法,WXEventModule是我们注册的名字,然后直接拉起push方法 bigAction(index){ console.log('will jump') weex.requireModule("WXEventModule").push("homeBig.js"); },
也许你已经注意到了,push里是一个js文件的名字,没错,这里直接穿入你要跳转的js的文件名,路径不需要了,在Xcode里面做处理;同时参数只有一个,如果需要传递参数有两种办法:
!)storage;
!!)在push中增加参数,比如:
//需要变动的地方 WX_EXPORT_METHOD(@selector(push:ids:)) - (void)push:(NSString *)url ids:(NSString *)ID { [self openURL:url ]; } //这里要提出的是如果还有其他原生需求的话这样的交互是没问题的,但是如果全是这样的js加载的界面,还是用storage的好,传过来数据会对VC造成影响,具体看下面;
4.这是重头戏,VC怎么来写?不可能我们一个js对应一个单独的VC,当然,这样写也可以,但是会很麻烦,这里分为两种情况:
!)全是js文件加载的界面;
!!)有weex的js界面,也有原生的界面;
如果有些功能需要用原生界面实现,并传递到原生界面,上面写到的传值就是最合适的方法,但是如果都是js界面则这样的传值毫无意义,因为你把从js拿到的值在新的VC再把值传给已经写好的js界面,且不说实现的问题,绕了一圈又把数据传给weex是不是很麻烦,所以weex之间传值建议storage,即使在Xcode中,因为集成了weex环境,依然支持storage,但仅限于weex的js之间。
下面来说这个VC怎么写,所有的js都用这个VC来加载:
#import <UIKit/UIKit.h> @interface HomeBigViewController : UIViewController @property (nonatomic, strong) NSURL *url; @end #import "HomeBigViewController.h" #import <WeexSDK/WXSDKInstance.h> @interface HomeBigViewController () @property (nonatomic, strong) WXSDKInstance *instance; @property (nonatomic, strong) UIView *weexView; @property (nonatomic, assign) CGFloat weexHeight; @property (nonatomic, assign) CGFloat top; @end @implementation HomeBigViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. self.view.backgroundColor = [UIColor whiteColor]; if (!self.navigationController.navigationBar.hidden) { _top = CGRectGetMaxY(self.navigationController.navigationBar.frame); } else{ _top = CGRectGetMaxY([[UIApplication sharedApplication]statusBarFrame]); } _weexHeight = self.view.frame.size.height - _top; [self render]; } - (void)dealloc { [_instance destroyInstance]; } - (void)viewWillAppear:(BOOL)animated { [self.navigationController.navigationBar setHidden:YES]; [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDefault; self.navigationController.navigationBar.barTintColor = [UIColor whiteColor]; self.navigationController.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName:[UIColor blueColor]}; [self.navigationController.navigationBar setBackgroundImage:[[UIImage alloc] init] forBarMetrics:UIBarMetricsDefault]; } - (void)render { _instance = [[WXSDKInstance alloc] init]; _instance.viewController = self; CGFloat width = self.view.frame.size.width; _instance.frame = CGRectMake(self.view.frame.size.width-width,_top, width, _weexHeight); __weak typeof(self) weakSelf = self; _instance.onCreate = ^(UIView *view) { [weakSelf.weexView removeFromSuperview]; weakSelf.weexView = view; [weakSelf.view addSubview:weakSelf.weexView]; UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, weakSelf.weexView); }; _instance.onFailed = ^(NSError *error) { NSLog(@"failed %@",error); }; _instance.renderFinish = ^(UIView *view) { NSLog(@"render finish"); }; _instance.updateFinish = ^(UIView *view) { NSLog(@"update Finish"); }; [_instance renderWithURL:_url options:@{@"bundleUrl": [NSString stringWithFormat:@"file://%@/bundlejs/components/",[NSBundle mainBundle].bundlePath]} data:nil]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end
除了对自定义module的描述,还有一个加载图片的注册,使用SDWebImage3.7.5,版本太高找不到方法:
[WXSDKEngine registerHandler:[WXImgLoaderDefaultImpl new] withProtocol:@protocol(WXImgLoaderProtocol)];
另外一个功能就是对weex的扩展,把原生界面内前进weex中,通过标签在weex中使用,其实都不复杂,可以看这里:http://weex-project.io/cn/guide/extend-ios.html
关于这个实现有个Demo给大家参考,不过在swift的写法里,一开始没发现,简直就是彩蛋,地址我发出来给大家参考:https://github.com/acton393/WeexOCExample
以上,学好,基本上weex算是入了个门了,接下来的问题就是封装,样式和对ES的了解了,到这里,你写的weex可以按照这种办法接入iOS项目里面了,这只是一种方式,方便做其他的原生处理,如果你自信纯weex没问题也可以直接用纯weex的包。
总结:博客写到这里,博主的weex学习道路也算告一段落了,如果你都看完了博主weex方面的博客,你也已经入门了,恭喜你,可以开始你的weex开发之路了。但这并不是终点,以后还会不定期更新,下一步,博主由于公司业务又要转战到华为的快应用开发,也许很快,关于快应用的坑和技术点博主就要开始更新了,欢迎大家阅读,一起学习。