Files
keyboard/keyBoard/Class/WebView/KBWebViewViewController.m
2025-11-10 16:09:47 +08:00

178 lines
6.0 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// KBWebViewViewController.m
// keyBoard
//
// Created by 张伟 on 2025/11/10.
//
#import "KBWebViewViewController.h"
#import <WebKit/WebKit.h>
@interface KBWebViewViewController () <WKNavigationDelegate, WKScriptMessageHandler>
@property(nonatomic, strong) WKWebView * webView;
// 🟢 顶部加载进度条
@property(nonatomic, strong) UIProgressView *progressView;
@property(nonatomic, assign) BOOL observingProgress;
@end
@implementation KBWebViewViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self configUI];
}
- (void)configUI {
// 1. 配置 JS 交互
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
WKUserContentController *userContentController = [[WKUserContentController alloc] init];
[userContentController addScriptMessageHandler:self name:@"keyBoard"];
config.userContentController = userContentController;
// 2. 创建 webView
self.webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:config];
self.webView.navigationDelegate = self;
self.webView.translatesAutoresizingMaskIntoConstraints = NO;
self.webView.backgroundColor = UIColor.clearColor;
self.webView.frame = self.view.bounds;
[self.view addSubview:self.webView];
// 🟢 3. 顶部 2 像素进度条
self.progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
self.progressView.translatesAutoresizingMaskIntoConstraints = NO;
self.progressView.trackTintColor = [UIColor clearColor]; // 背景透明
self.progressView.progressTintColor = [UIColor greenColor];
self.progressView.progress = 0.0f;
self.progressView.hidden = YES; // 初始隐藏
[self.view addSubview:self.progressView];
// 约束:贴在最上面,高度 2 像素,左右撑满
[NSLayoutConstraint activateConstraints:@[
[self.progressView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor],
[self.progressView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[self.progressView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
[self.progressView.heightAnchor constraintEqualToConstant:2.0]
]];
// 🟢 4. 监听 WKWebView 加载进度estimatedProgress
[self.webView addObserver:self
forKeyPath:@"estimatedProgress"
options:NSKeyValueObservingOptionNew
context:nil];
self.observingProgress = YES;
// 5. 加载 URL
NSURLRequest * req = [NSURLRequest requestWithURL:[NSURL URLWithString:self.url]];
[self.webView loadRequest:req];
}
#pragma mark - KVO: 监听加载进度estimatedProgress 🟢
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary<NSKeyValueChangeKey,id> *)change
context:(void *)context {
if (object == self.webView && [keyPath isEqualToString:@"estimatedProgress"]) {
CGFloat progress = self.webView.estimatedProgress;
// 0 ~ 1之间的进度
self.progressView.hidden = NO;
[self.progressView setProgress:progress animated:YES];
if (progress >= 1.0f) {
// 加载完成后延迟一点点再隐藏,顺滑一点
[UIView animateWithDuration:0.25
delay:0.25
options:UIViewAnimationOptionCurveEaseOut
animations:^{
self.progressView.alpha = 0.0;
} completion:^(BOOL finished) {
self.progressView.progress = 0.0;
self.progressView.hidden = YES;
self.progressView.alpha = 1.0;
}];
}
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
#pragma mark - WKNavigationDelegate
// 开始加载
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
NSLog(@"开始加载url");
// 开始加载时,确保进度条出现
self.progressView.hidden = NO;
self.progressView.progress = 0.0;
}
// 加载完成
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
NSLog(@"页面加载成功");
self.title = webView.title;
}
// 加载失败
- (void)webView:(WKWebView *)webView
didFailProvisionalNavigation:(WKNavigation *)navigation
withError:(NSError *)error {
NSLog(@"webView load error: %@", error);
// 失败时也把进度条收一下
self.progressView.hidden = YES;
self.progressView.progress = 0.0;
}
#pragma mark - WKScriptMessageHandler JS 调原生)
- (void)userContentController:(WKUserContentController *)userContentController
didReceiveScriptMessage:(WKScriptMessage *)message {
if (![message.body isKindOfClass:NSDictionary.class]) {
NSLog(@"Body参数不合法");
return;
}
[self handleJSMethodWithParams:message.body];
}
- (void)handleJSMethodWithParams:(NSDictionary *)params {
NSDictionary * body = [params copy];
NSLog(@"收到 JS 消息: %@", body);
NSString * type = body[@"type"];
// 测试打印
if ([type isEqual:@"ONE_METHOD"]) {
NSLog(@"come on baby js 调用你的方法了");
}
// 修改title
if ([type isEqual:@"changeTiele"]) {
NSLog(@"%@", body);
NSString * newTiele = body[@"payload"][@"data"];
self.title = newTiele;
}
}
#pragma mark - Clean up 🟢
- (void)dealloc {
if (self.observingProgress) {
@try {
[self.webView removeObserver:self forKeyPath:@"estimatedProgress"];
} @catch (NSException *exception) {
NSLog(@"removeObserver estimatedProgress exception: %@", exception);
}
}
// 顺便把 JS 通道也移除,避免潜在的循环引用
[self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"keyBoard"];
}
@end