对于你的“容器”而言,weex只是View层。
“请牢记上述的格言”,个人推荐大家在配置Cocoapods的时候,既要有weex团队打包好的SDK,也要有引入源码的准备。
pod 'WeexSDK', '0.9.4'
# pod 'WeexSDK', :path => '/User/icepy/weex/ios/sdk'
pod 'WXDevtool', '0.8.2'
# pod 'WXDevtool', :path => '/User/icepy/WXDevtool'
默认,你已经把环境准备完毕
初始化
既然weex只是View层,对于它接入,应该就比较简单了。
参考:weex-project.io/doc/advance…
参考:weex-project.io/doc/advance…
理论上,weex的初始化应该在App启动时。但是,你也可以在特定的时候初始化weex。
[WXSDKEngine initSDKEnviroment];
当然,如果你需要有一点业务的配置,也可以使用 WXAppConfiguration,因为这不是必须的。
[WXAppConfiguration setAppVersion:@""];
[WXAppConfiguration setAppName:@""];
[WXAppConfiguration setAppGroup:@""];
有时候日志信息,也是非常必要的,你可以使用 WXLog 来配置
[WXLog setLogLevel:WXLogLevelAll]
日志等级,有一组枚举,你可以查看一下
typedef NS_ENUM(NSUInteger, WXLogLevel){
/**
* No logs 没有日志
*/
WXLogLevelOff = 0,
/**
* Error only 仅仅是错误信息
*/
WXLogLevelError = WXLogFlagError,
/**
* Error and warning 错误和警告
*/
WXLogLevelWarning = WXLogLevelError | WXLogFlagWarning,
/**
* Error, warning and info 错误,警告,信息
*/
WXLogLevelInfo = WXLogLevelWarning | WXLogFlagInfo,
/**
* Log, warning info 这里的log代表了js层面的console.log,可以在Xcode控制台中可见
*/
WXLogLevelLog = WXLogFlagLog | WXLogLevelInfo,
/**
* Error, warning, info and debug logs
*/
WXLogLevelDebug = WXLogLevelLog | WXLogFlagDebug,
/**
* All
*/
WXLogLevelAll = NSUIntegerMax
};
完善你的ViewController
前言讲到了weex只是一层View,那么将它和UIView划等号也是可以的。在你的VC中,应该有一个URL的属性,可以接到js bundle 文件。
- (instancetype)initWithURL:(NSURL *)url
{
self = [super init];
if (self) {
_url = url;
}
return self;
}
@interface ViewController ()
@property(nonatomic, strong) WXSDKInstance *instance;
@property(nonatomic, strong) UIView *weexView;
@property(nonatomic, strong) NSURL *url;
@end
然后在 viewDidLoad 中进行初始化。
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self render]
}
- (void) render {
CGFloat width = self.view.frame.size.width;
[self.instance destroyInstance];
self.instance = [[WXSDKInstance alloc] init];
self.instance.viewController = self;
self.instance.frame = CGRectMake(self.view.frame.size.width - width, self.top, width, self.weexHeight);
__weak typeof(self) weakSelf = self;
self.instance.onCreate = ^(UIView *view){
[weakSelf.weexView removeFromSuperview];
weakSelf.weexView = view;
[weakSelf.view addSubview:weakSelf.weexView];
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, weakSelf.weexView);
};
self.instance.onFailed = ^(NSError *error){
NSLog(@"%@",error.userInfo);
};
self.instance.renderFinish = ^(UIView *view){
[weakSelf.instance fireGlobalEvent:@"geolocation" params:@{@"key":@"value"}];
};
[self.instance renderWithURL:self.url options:nil data:nil];
}
从上述的逻辑来看,应该可以推敲出,weex 渲染结果虽然需要一个UIView来承接,最后再将这个UIView替换掉系统的view,所以理论上,你可以生成多个weex的instance,来拼凑页面,只需要设置好frame即可。weex 在代码层面上提供了几个block,来让你感知到渲染阶段的几个周期,比如是渲染错误了,还是渲染完成了,还是在渲染创建之前。
最后,别忘记了在 dealloc 里调用一下 destroyInstanc 来销毁 weex 实例,不然会内存溢出。
-(void)dealloc{
[self.instance destroyInstance];
}
到此,weex可以将你用web技术写好的页面,呈现在对应的View中。不过,一个应用如果都是纯展示,那么到此就结束了,但往往不是。也许,你还需要各种各样Native的能力,也许Native也需要各种各样JS的能力。
且看看 weex 为我们提供了多少种方式。
JS Call Native
weex 提供了Module来让JS主动Call Native,第一步你还是需要注册你的 Module。
[WXSDKEngine registerModule:@"test-logger" withClass: [WXLoggerModule class]];
// WXLoggerModule.h
#import <Foundation/Foundation.h>
#import <WeexSDK/WXModuleProtocol.h>
@interface WXLoggerModule : NSObject <WXModuleProtocol>
@end
// WXLoggerModule.m
#import "WXLoggerModule.h"
#import <WeexSDK/WeexSDK.h>
@interface WXLoggerModule()
@end
@implementation WXLoggerModule
@synthesize weexInstance;
WX_EXPORT_METHOD(@selector(info:callback:));
- (void) info: (NSDictionary *) log callback:(WXKeepAliveCallback) callback{
NSLog(@"WXLoggerModule ----> : %@",log);
callback(@{@"success":@YES,@"address":@"beijing"},YES);
}
@end
// .js 文件
var logger = require('@weex-module/test-logger');
logger.info({name:"icepy"});
Native Call JS
目前来说Native主动去Call JS,还只能使用事件的方式。
var globalEvent = require('@weex-module/globalEvent');
globalEvent.addEventListener('nativecalljs',function (e){
});
self.instance.renderFinish = ^(UIView *view){
[weakSelf.instance fireGlobalEvent:@"nativecalljs" params:@{@"name":@"icepy"}];
};
组件
从业务层面来说JS与Native可以互相通信,这是非常重要的一点,但是如果当前端有无法实现的或者很难实现的组件时,这个时候Component就派上用场了。
[WXSDKEngine registerComponent:@"test-image" withClass:[WXImageComponent class]];
//WXImageComponent.h
#import <WeexSDK/WeexSDK.h>
@interface WXImageComponent : WXComponent
@property(nonatomic, strong) NSString *imageSrc;
@end
//WXImageComponent.m
#import "WXImageComponent.h"
static CGFloat IMAGEWIDTH = 320;
static CGFloat IMAGEHEIGHT = 320;
@implementation WXImageComponent
-(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]) {
_imageSrc = [WXConvert NSString:attributes[@"src"]];
}
return self;
}
-(void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"DTWXImgaeCompnent ---- > %@",self.imageSrc);
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 20, IMAGEWIDTH, IMAGEHEIGHT)];
imageView.userInteractionEnabled = YES;
imageView.clipsToBounds = YES;
imageView.exclusiveTouch = YES;
imageView.contentMode = UIViewContentModeScaleToFill;
NSURL *imageURL = [NSURL URLWithString:self.imageSrc];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage *image = [UIImage imageWithData:imageData];
imageView.image = image;
[self.view addSubview:imageView];
}
@end
使用起来就和使用Vue的组件类似
<test-image src=""></test-image>
其实,组件还有大量的生命周期,在这些生命周期内,你可以进行一些处理,总体来说,这是一个很有趣的事情。
关注与我共创
更多精彩内容可关注我的个人微信公众号:搜索fed-talk或者扫描下列二维码,也欢迎您将它分享给自己的朋友。
