《weex 实践指北》第二章:客户端接入 weex(iOS 视角)

organiclion 发布于8天前 阅读614次
0 条评论

对于你的“容器”而言,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层,对于它接入,应该就比较简单了。

参考: https://weex-project.io/doc/advanced/integrate-to-ios.html

参考: https://weex-project.io/doc/advanced/extend-to-ios.html

理论上,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或者扫描下列二维码,也欢迎您将它分享给自己的朋友。

《weex 实践指北》第二章:客户端接入 weex(iOS 视角)

查看原文: https://github.com/icepy/we-writing/issues/42

共收到0条回复

需要 登录 后回复方可回复, 如果你还没有账号你可以 注册 一个帐号。