iOS问题汇总之iOS应用 - Web Hybrid混合页面开发关键点
08 September 2020
iOS问题汇总之iOS应用 - Web Hybrid混合页面开发关键点
Web Hybrid关键点
HybridWeb混合页面
视图结构
safeAreaView(UIView)
|——searchBar(UIView)
|——scrollView(UIScrollView)
|——contentView(UIView)
|——bannerView(UIView)
|——mainWebView(WKWebView)
需要根据document.body.offsetHeight
动态更新WebView的高度,以保证只有最外层的Scroll有效
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey, id> *)change context:(void *)context {
if ([keyPath isEqualToString:@"contentSize"] && self.canKVOSetScrollViewHeight) {
[self evaluateJavaScript:@"document.body.offsetHeight" completionHandler:^(id _Nullable scrollHeight, NSError *_Nullable error) {
CGFloat height = [scrollHeight floatValue];
if (self.webContentHeight != height && height > 1) {
self.webContentHeight = height;
[self.mainWebView mas_updateConstraints:^(MASConstraintMaker *make) {
make.height.mas_greaterThanOrEqualTo(self.webContentHeight);
}];
[self.safeAreaView layoutIfNeeded];
}
}];
}
}
VirtualView虚拟视图+JSCore关键点
VirtualView
- CALayer的属性包装成虚拟视图结点;图层渲染前创建的过程,就是虚拟Node结点合并的过程;
- KVO实现对Layout、颜色等属性变化的更新;
- 核心类VVViewContainer继承自UIView,所有视图组合的图层的承载容器;
- 自定属性结点可组合自定义UIView;
VirtualViewDelegate
- (void)virtualViewClickedWithAction:(NSString *)action andValue:(NSString *)value;
把一个类做成可字典方式取值与设值,实现两个方法即可:
- (JSValue *)objectForKeyedSubscript:(id)key ;
- (void)setObject:(id)object forKeyedSubscript:(NSObject <NSCopying> *)key ;
JSCore与JSContext
从UIWebView获得JSContext实例
self.webViewJSContext = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
//注册native方法
self.webViewJSContext[@"pnu_log"] = ^(NSString *text) {
PPDNativeLog(@"[PPDNative] pnu_log:%@", text);
// [[[UIAlertView alloc] initWithTitle:nil message:text delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
};
直接生成JSContext实例
JSContext *jsContext = [[JSContext alloc] init];
[jsContext evaluateScript:jsText withSourceURL:[NSURL fileURLWithPath:jsPath]];
采用JSContext实现JS调用原生,使用案例
注册native方法
self.webViewJSContext[@"native_request"] = ^(id value,JSValue *callback) {
strongify(self)
//把value构造成jsReuest
JSRequest *jsRequest = [self jsRequestWithValue:value];
if(!jsRequest){
return;
}
jsRequest.successCallback = callback;
jsRequest.errorCallback = callback;
//拆解jsRequest,构造原生的网络请求
[self requestWithJSRequest:jsRequest];
};
JS端调用
function nativeRequest(request, responseCallback) {
var request = {
"url": "http://baidu.com/xxxx",
"method": "POST",
"params": {"name":"David"}
}
native_request(JSON.stringify(request),
function (responseString) {
responseCallback(JSON.parse(responseString))
}
)
}
其他
同步方法获得iOS设备权限
请求相机权限
//请求相机权限
+ (BOOL)checkCameraAccess {
BOOL isPhotoSupport = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];
if(!isPhotoSupport){
[LWBaseViewController showHUDWithMessage:NSLocalizedString(@"Not Surpport Camera", nil)];
return NO;
}
__block BOOL isSuccess = NO;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
//非主线程
if (granted) {
isSuccess = YES;
dispatch_semaphore_signal(semaphore);
} else {
dispatch_semaphore_signal(semaphore);
}
}];
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
return isSuccess;
}