撒网要见鱼 1 小时前发布
18 年元旦三天内和朋友突击了下,勉强是将雏形做出来了,后续的 API 慢慢完善。(当然了,主力还是那个朋友,本人只是初涉 iOS,勉强能看懂,修修改改而已)
大致内容如下:
这个项目中,为了方便,就没有分成多个静态库了(事实上是可以这样做的),而是全部都放在一个项目中
整体目录结构如下:
- quickhybrid-ios
- |- AppDelegate // 应用入口,分发进入对应的viewcontroller
- |- core // 核心工具类,放一些通用工具类
- | |- ui
- | |- util
- | |- ...
- |- quickhybrid // JSBridge实现的核心代码,定制viewcontroller,实现API等
- | |- webViewJavascriptBridge
- | |- basecore
- | |- quickcore
- | |- api
和 Android 一样,仍然是简单的三次架构:
- 底层核心工具类 - >JSBridge桥接实现 - >app应用实现
其中,core 和 jsbridge 有必要的话可以打包成静态库
- core
- |- ui // 一些UI效果的定义与实现
- |- util // 通用工具类
- quickhybird
- |- WebViewJavascriptBridge // 第三方开源的jsbridge实现,里面进行了修改
- |- basecore // 定义基类viewcontroller
- |- quickcore // 定义quickhybrid中的viewcontroller实现
- |- api // 定义API,开放原生功能给H5
- 应用内
- |- AppDelegate // 应用入口,分发进入对应的viewcontroller
- |- MainViewController // 入口界面
- |- TestPayApi // 定义的一个测试支付组件(自定义)API
- |- qhjsmodules.plist // 内部定义模块的别名于路径关系的配置文件
iOS 可以直接在 info.plist 中配置权限,譬如
- <key>NSAppTransportSecurity</key>
- <dict>
- <key>NSAllowsArbitraryLoads</key>
- <true/>
- </dict>
- <key>NSCameraUsageDescription</key>
- <string>是否允许应用使用摄像头?</string>
- <key>NSLocationWhenInUseUsageDescription</key>
- <string>是否允许应用使用定位功能</string>
- <key>NSMicrophoneUsageDescription</key>
- <string>是否允许应用使用麦克风?</string>
- <key>NSPhotoLibraryUsageDescription</key>
- <string>是否允许访问相册</string>
- <key>UIFileSharingEnabled</key>
- ...
- Bundle Identifier: com.quickhybrid.quickhybriddemo
- Version: 1.0.0
- Deployment Target: 11.2(默认最新调试)
- Devices: Universal
- Signing: none
相比 Android 中一堆复杂的配置,iOS 中无疑简单很多,直接用最新系统调试即可。。。
这里,到目前位置,这个项目还有很多 API 没有实现,后续预计是会引入部分静态库的。
当然,如果想要引入静态库,也很简单,直接如下:
- 项目配置 - >Build Phases - >Link Binary With Libraries - >+(添加) - >然后需要用到的地方import即可
整个过程非常的轻松愉快。
代码方面,也无法一一全部说明,这里仅列举一些比较重要的步骤实现,其余可参考源码
前面的 JS 项目中就已经有提到 UA 约定,就是在加载对于 webview 时,统一在 webview 中加上如下 UA 标识
- // 获取默认UA
- NSString * defaultUA = [[UIWebView new] stringByEvaluatingJavaScriptFromString: @"navigator.userAgent"];
- NSString * version = @"1.0.0";
- NSString * customerUA = [defaultUA stringByAppendingString: [NSString stringWithFormat: @" QuickHybridJs/%@", version]]; [[NSUserDefaults standardUserDefaults] registerDefaults: @ {@"UserAgent": customerUA
- }];
在创建 webview 时,QHBaseWebLoader 里创建代理监听
- // 创建webView容器
- WKWebViewConfiguration *webConfig = [[WKWebViewConfiguration alloc] init];
- WKUserContentController *userContentVC = [[WKUserContentController alloc] init];
- webConfig.userContentController = userContentVC;
- WKWebView *wk = [[WKWebView alloc] initWithFrame:CGRectZero configuration:webConfig];
- [self.view addSubview:wk];
- self.wv = wk;
- self.wv.navigationDelegate = self;
- self.wv.UIDelegate = self;
- self.wv.translatesAutoresizingMaskIntoConstraints = NO;
- ...
- self.bridge = [WKWebViewJavascriptBridge bridgeForWebView:self.wv];
- [self.bridge setWebViewDelegate:self];
- [self.wv.configuration.userContentController addScriptMessageHandler:self.bridge name:@"WKWebViewJavascriptBridge"];
然后 h5 中通过以下调用:
- window.webkit.messageHandlers.WKWebViewJavascriptBridge.postMessage(...);
然后
内部,接受传递的信息,并自行解析
- WKWebViewJavascriptBridge
- #pragma mark - WKScriptMessageHandler
- - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
- if ([message.name isEqualToString:@"WKWebViewJavascriptBridge"]) {
- [self excuteMessage:message.body];
- }
- }
iOS 中还有一点和 Android 不同就是,很多标准的 html5 内容无需额外兼容(譬如 fileinput 文件选择等)
其它内容,和 Android 实现中提到的一样,这里就不再赘述了,可以直接参考源码
另外,后续如果继续有容器优化等操作,也会单独整理,加入本系列。
为了方便,直接集成到了 res / 中,入口页面默认会加载它,也可以直接看源码
github 上这个框架的实现
quickhybrid/quickhybrid来源: https://segmentfault.com/a/1190000012689126