weex ios 集成
参阅:Weex学习与实践:iOS原理篇
swift集成weex
首先将weexsdk集成到项目中,同OC
将weex的WeexSDK.framework导入
将main.js导入项目中。main.js在weex的WeexSDK.framework中
swift 使用weex
1、初始化weex和调用
import WeexSDK
AppDelegate.Swift中
WXAppConfiguration.setAppGroup("SwiftWeexSample")
WXAppConfiguration.setAppName("SwiftWeexSample")
WXAppConfiguration.setAppVersion("1.0.0")
WXLog.setLogLevel(WXLogLevel.All)
//init WeexSDK
WXSDKEngine.initSDKEnviroment()
ViewController.Swift中
//
// ViewController.swift
// SwiftWeexSample
//
// Created by zifan.zx on 6/18/16.
// Copyright © 2016 com.taobao.weex. All rights reserved.
//
import UIKit
import WeexSDK
class ViewController: UIViewController {
var instance:WXSDKInstance?;
var weexView = UIView()
var weexHeight:CGFloat?;
var top:CGFloat?;
var url:NSURL?;
override func viewDidLoad() {
super.viewDidLoad()
if !self.navigationController!.navigationBar.hidden {
top = CGRectGetMaxY(self.navigationController!.navigationBar.frame);
} else {
top = CGRectGetMaxY(UIApplication.sharedApplication().statusBarFrame)
}
weexHeight = self.view.frame.size.height - top!;
render()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
deinit {
if instance != nil {
instance!.destroyInstance()
}
}
func render(){
if instance != nil {
instance!.destroyInstance()
}
instance = WXSDKInstance();
instance!.viewController = self
let width = self.view.frame.size.width
instance!.frame = CGRectMake(self.view.frame.size.width-width, top!, width, weexHeight!)
weak var weakSelf:ViewController? = self
instance!.onCreate = {
(view:UIView!)-> Void in
weakSelf!.weexView.removeFromSuperview()
weakSelf!.weexView = view;
weakSelf!.view.addSubview(self.weexView)
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, weakSelf!.weexView)
}
instance!.onFailed = {
(error:NSError!)-> Void in
print("faild at error: %@", error)
}
instance!.renderFinish = {
(view:UIView!)-> Void in
print("render finish")
}
instance!.updateFinish = {
(view:UIView!)-> Void in
print("update finish")
}
instance!.renderWithURL(url, options: ["bundleUrl":String.init(format: "file://%@/bundlejs/", NSBundle.mainBundle().bundlePath)], data: nil)
}
}
2、module 扩展,自定义模块
有些时候我们希望JS层面能够调用Native的一些功能,比如通过JS代码让Native打开一个特定的url。这时候,我们可以自定义一个模块向JS层面暴露API:
因为module
暴露method
是通过 Objective-C
宏来做的,调用的时候是通过反射,所以Swift
扩展module
通过extension Objective-C
的类,以下操作,可以直接在weex 的iOS playground
中进行
1、拓展module
新建WXSwiftTestModule.h/m
和 WXSwiftTestModule.swift
文件, 在新建Swift文件的时候会提示
选择 Create Bridging Header
, 因为我们要在swift中访问Objective-C
的一些类,正是通过这个header暴露OC的类给Swift,header格式为 yourTarget-Bridging-Header.h
,我这里创建完header文件名称为:WeexDemo-Bridging-Header.h
WXSwiftTestModule.h/m 中实现
WXSwiftTestModule.m 中
/**
* Created by Weex.
* Copyright (c) 2016, Alibaba, Inc. All rights reserved.
*
* This source code is licensed under the Apache Licence 2.0.
* For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
*/
#import
#import
@interface WXEventModule : NSObject
@end
WXSwiftTestModule.m 中
WeexDemo-Swift.h 这个文件需要编译一下才可以搜索到,具体的路径
/**
* Created by Weex.
* Copyright (c) 2016, Alibaba, Inc. All rights reserved.
*
* This source code is licensed under the Apache Licence 2.0.
* For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
*/
#import "WXEventModule.h"
#import "SwiftWeexSample-Bridging-Header.h"
@implementation WXEventModule
@synthesize weexInstance;
WX_EXPORT_METHOD(@selector(openURL:))
@end
Swift 中实现
- 扩展 OC的类 WXSwiftTestModule ,增加了一个方法,这个方法就是我们要暴露出来,在js中可以调到的
//
// WXEventModule.swift
// SwiftWeexSample
//
// Created by zifan.zx on 24/09/2016.
// Copyright © 2016 com.taobao.weex. All rights reserved.
//
import Foundation
public extension WXEventModule {
public func openURL(url:String) {
var newUrl:String = url;
if url.hasPrefix("//") {
newUrl = String.init(format: "http://%@", url);
}else if !url.hasPrefix("http") {
//relative path
newUrl = (NSURL.init(string: url, relativeToURL: weexInstance.scriptURL)!.absoluteString)!
}
let controller:ViewController = ViewController()
controller.url = NSURL.init(string: newUrl)
weexInstance.viewController.navigationController?.pushViewController(controller, animated:true)
}
}
如果需要调用oc的类,需要在SwiftWeexSample-Bridging-Header
中暴露。
至此这个Swift的简单的module 已经算是开发完成
注意点如下:
- 需要遵循WXModuleProtocol协议;
- 需要合成(synthesize)weexInstance属性;
- 使用WX_EXPORT_METHOD来暴露API;
- 使用WXModuleCallback进行回调;
2、module 使用
1、在注册weex时,注册module
// register event module
WXSDKEngine.registerModule("event", withClass: NSClassFromString("WXEventModule"))
2、we 文件中使用
Swift Module
3、下载图片
weex中没有直接下载图片的方法,所以需要进行以下操作。
在项目中,导入SDWebImage
新建WXImgLoaderDefaultImpl.h/m
文件,在.h文件中
/**
* Created by Weex.
* Copyright (c) 2016, Alibaba, Inc. All rights reserved.
*
* This source code is licensed under the Apache Licence 2.0.
* For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
*/
#import
#import
@interface WXImgLoaderDefaultImpl : NSObject
@end
.m文件中
/**
* Created by Weex.
* Copyright (c) 2016, Alibaba, Inc. All rights reserved.
*
* This source code is licensed under the Apache Licence 2.0.
* For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
*/
#import "WXImgLoaderDefaultImpl.h"
#import "SDWebImageManager.h"
#define MIN_IMAGE_WIDTH 36
#define MIN_IMAGE_HEIGHT 36
#if OS_OBJECT_USE_OBJC
#undef WXDispatchQueueRelease
#undef WXDispatchQueueSetterSementics
#define WXDispatchQueueRelease(q)
#define WXDispatchQueueSetterSementics strong
#else
#undef WXDispatchQueueRelease
#undef WXDispatchQueueSetterSementics
#define WXDispatchQueueRelease(q) (dispatch_release(q))
#define WXDispatchQueueSetterSementics assign
#endif
@interface WXImgLoaderDefaultImpl()
@property (WXDispatchQueueSetterSementics, nonatomic) dispatch_queue_t ioQueue;
@end
@implementation WXImgLoaderDefaultImpl
#pragma mark -
#pragma mark WXImgLoaderProtocol
- (id)downloadImageWithURL:(NSString *)url imageFrame:(CGRect)imageFrame userInfo:(NSDictionary *)userInfo completed:(void(^)(UIImage *image, NSError *error, BOOL finished))completedBlock
{
if ([url hasPrefix:@"//"]) {
url = [@"http:" stringByAppendingString:url];
}
return (id)[[SDWebImageManager sharedManager] downloadImageWithURL:[NSURL URLWithString:url] options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize) {
} completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
if (completedBlock) {
completedBlock(image, error, finished);
}
}];
}
@end
然后再注册weex时,注册handler
// register handler
WXSDKEngine.registerHandler(WXImgLoaderDefaultImpl(), withProtocol:NSProtocolFromString("WXImgLoaderProtocol"))
4、自定义UI组件
如果Weex的内置标签不足以满足要求时,我们可以自定义Native组件,然后暴露给.we文件使用。
比如我们可以定义一个WXButton
,继承自WXComponent
,
1.创建UI组件WXButton,继承自WXComponent
WXButton.h中
//
// WXButton.h
// LSWeexSwiftDemo
//
// Created by John_LS on 2016/11/15.
// Copyright © 2016年 John_LS. All rights reserved.
//
#import
@interface WXButton : WXComponent
@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) UIButton *innerButton;
@end
在WXButton.m中
//
// WXButton.m
// LSWeexSwiftDemo
//
// Created by John_LS on 2016/11/15.
// Copyright © 2016年 John_LS. All rights reserved.
//
#import "WXButton.h"
@implementation WXButton
-(instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDictionary *)styles attributes:(NSDictionary *)attributes events:(NSArray *)events weexInstance:(WXSDKInstance *)weexInstance{
self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance];
if (self) {
self.title = [WXConvert NSString:attributes[@"title"]];
}
return self;
}
-(void)viewDidLoad{
[super viewDidLoad];
self.innerButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.innerButton.frame = self.view.bounds;
[self.view addSubview:self.innerButton];
[self.innerButton setTitle:self.title forState:UIControlStateNormal];
[self.innerButton addTarget:self action:@selector(onButtonClick:)
forControlEvents:UIControlEventTouchUpInside];
}
-(void)onButtonClick:(UIButton*)btn{
NSLog(@"按钮被onButtonClick击了");
}
@end
其中,在
-(instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDictionary *)styles attributes:(NSDictionary *)attributes events:(NSArray *)events weexInstance:(WXSDKInstance *)weexInstance{
self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance];
if (self) {
self.title = [WXConvert NSString:attributes[@"title"]];
}
return self;
}
方法中可以获得we文件标签里面的属性,如title,通过这些属性,我们可以在组件生命周期中修改组件的样式,比如上面已经设置了按钮的title。
2、然后将其注册进Weex SDK:
// register component
WXSDKEngine.registerComponent("weex-button", with: NSClassFromString("WXButton"))
3、在we文件中调用按钮标签
Hello Weex
注:we文件中按钮的标签要与注册weexSDK时填写的字符串一致。