混合开发经历总结
作为iOS开发,native的一些缺陷,确实使得一些业务无法保证,混合开发目前来说,毫无疑问是最符合当前移动端的一种方式.混合开发无非是native与JS交互的问题,第一版本我们以WKWebView为主,native作为框架,考虑到web微信端(公众号)已经完成,尽量做到代码复用.
Web数据共享的问题
web存储主要为LocalStorage,SessionStorage这两种存储方式,我们方案是把数据缓存在本地,我目前用的plist文件,而这种方式,在iOS端get数据时无法同步返回,这里用的是WKWebView与JS交互的方式.
- 业务需要我们要在JS开始执行之前注入JS
WKWebViewConfiguration * configuration = [[WKWebViewConfiguration alloc] init];
WKUserContentController * userContent = [[WKUserContentController alloc] init];
[userContent addScriptMessageHandler:self name:@"login"];
NSString * js = [NSString stringWithFormat:@"window.localStorage.setItem('%@','%@')",key,value];
WKUserScript * userScript = [[WKUserScript alloc]initWithSource:js injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
[userContent addUserScript:userScript];
configuration.userContentController = userContent;
self.wkWebView = [[WKWebView alloc]initWithFrame:CGRectMake(0,0, kWindowWidth, kWindowHeigth) configuration:configuration];
//JS端调用方法
window.webkit.messageHandlers.login.postMessage({body: 'login'});
可以通过addScriptMessageHandler添加需要的set,remove方法,通过上述代码与JS交互后,native实现WKScriptMessageHandler协议方法,实现JS调用native,其实只有一个...
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;
目前是中这种思路去做的,但是这种方式无法实现同步给js返回值,而且数据变化时只能重新加载一遍WebView去注入数据,效果不好,解决思路:
- 用JavaScriptCore去做数据共享这方面,但是实践发现依旧不能实现同步,有时会拿不到值.
- WKWebView的坑确实很烦,在文章末尾会举例说明.
- 比较Weex或RN,主要是微信端用的是Vue.js,最终选择Weex.
- 追求60分的前提下,完全可以做到三端复 ,但是在追求90分的情况下,追求三端复的结果,未必分开编写来的效率。
Weex
第二版本只是首页和地址选择的一些界面用Weex,首先性能方面确实要比WebView强大,而且最后Weex也会转换为native去渲染.后面会慢慢过渡到weex.
- weex中Storage也是用plist文件存储,但是weex中Srorage也是异步,这里通过weex的Module扩展weex数据与web数据共享
- 包括weex跳转原生webView同理
// set等其他方法同理
WX_EXPORT_METHOD(@selector(getStorageItem: callback:))
-(void)getStorageItem:(NSString *)key callback:(WXModuleKeepAliveCallback)callback
WKWebView的坑
- 目前在WebView中JS第一次发送请求时失败,导致界面需要重新刷新.有解决的或遇到这些问题的人欢迎一起讨论交流.
- WKWebView内存泄漏的问题,记得在控制器销毁时,移除所有添加的ScriptMessageHandler
- (void)removeScriptMessageHandlerForName:(NSString *)name;
网友评论