WKWebView的使用、优化和封装(VDWebView)
VDWebView的源码和使用示例
VDWebView带来的便捷
- 以最少的成本替代旧项目中的UIWebView
- 熟习的代理商方法
- 常用的基本方法和属性
- 使用起来更加的熟习只要把
UIWebView
名更换为VDWebView
- 更加方便和安全的JS调用OC方法(后面我会具体说明处理方案)
- 支持以target-action的方式替代delegate(两者任意选择)
- 不会出现相似于使用WKWebView注册OC方法不记得注销导致循环引用无法释放的问题
- 提供加载进度条的使用、预估进度值的读取等
CocoaPods
pod 'VDWebView', '~> 1.0.0'
基本形容
- 为什么用的是
WKWebView
- 提供熟习和更加便捷的属性和方法(结合了
UIWebView
和WKWebView
) - JS调用OC方法的绑定
- JS的调用和注入
为什么使用WKWebView
WKWebView
是iOS8后推出的WebKit框架中的控件,因为iOS12后已经弃用UIWebView
了而且现在的大多数项目只适配到iOS8- 加载速度优于
UIWebView
且处理了加载网页时的内存泄露问题 - 在和JS交互方面提供了桥梁
WKUserContentController
- 没好处这东西出来干嘛,所以综上用起来吧
提供了哪些更加熟习和更加便捷的属性和方法
VDWebViewDelegate
- 类
UIWebView
代理商方法,解决对象(WKNavigationDelegate
)
/// 类UIWebView代理商方法- (void)webViewDidStartLoad:(VDWebView *)webView;- (void)webViewDidFinishLoad:(VDWebView *)webView;- (void)webView:(VDWebView *)webView didFailLoadWithError:(NSError *)error;- (BOOL)webView:(VDWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
- 对
WKUIDelegate
和WKScriptMessageHandler
代理商的合并
/** JS调原生代理商方法(注册了过的方法将一律通过此方法回调) @param webView VDWebView @param message 回调消息 */- (void)webView:(VDWebView *)webView didReceiveScriptMessage:(WKScriptMessage *)message;/** JS弹框阻拦方法--假如需要自己设置弹框建议公告此方法 @param webView VDWebView @param type 弹框类型 @param title 标题 @param content 内容 @param completionHandler 结果解决必需执行completionHandler(data) */- (void)webView:(VDWebView *)webView showAlertWithType:(VDJSAlertType)type title:(NSString *)title content:(NSString *)content completionHandler:(void (^)(id))completionHandler;
新添加了哪些属性和方法
///预估网页加载进度@property (nonatomic, readonly) CGFloat estimatedProgress;// 能否显示进度条 默认不显示@property (nonatomic, assign) BOOL isShowProgressBar;///进度条@property (nonatomic, strong) UIView *progressBar;/** web页面加载完毕后的内容高度(在页面加载完成后获取) */@property (nonatomic, readonly) CGFloat *contentHeight;/// 能否启用js调用原生弹框 默认为NO 禁止(默认加载弹框在根试图)@property (nonatomic, assign) BOOL enableAllAlert;@property (nonatomic, assign) BOOL enableAlert;@property (nonatomic, assign) BOOL enableConfirm;@property (nonatomic, assign) BOOL enablePrompt;///back 层数- (NSInteger)countOfHistory;- (void)gobackWithStep:(NSInteger)step;
JS调用OC方法的绑定
在使用WKWebView
时我们需要调用WKWebView
内configuration
中的userContentController
所属类WKUserContentController
提供的实例方法进行注册,具体方法如下:
- (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name;
对应的注销方法为:
- (void)removeScriptMessageHandlerForName:(NSString *)name;
已知的循环引用问题
在使用addScriptMessageHandler:name:
方法注册时传入的这个handler被循环引用,假如不调用对应的注销方法就会导致handler这个对象无法被释放,假如你这个handler传入是webView所在的控制器,那么你就要在销毁这个控制器前注销掉你注册的方法.
tip: 如何知道控制器有没有被释放,重写dealloc(),没走此方法说明未被释放
VDWebView是如何处理循环引用问题
简要分析可分为下面三步
- 使用
VDScripMessageHandler
作为注册的handler- 继承协议
WKScriptMessageHandler
- 提供target-action回调方式
- 继承协议
- 保存注册记录
- 在
VDWebView
的dealloc()
方法中获取注册记录并注销
这些做的好处在于你在使用VDWebView时无需自己去一个个手动注销了(假如你注册的方法多的话那就是噩梦了)
VDWebView是如何进行方法的注册和回调的
- 方法的注册
- (void)addScriptMessageHandler:(id)scriptMessageHandler name:(NSString *)name;
- JS调用说明
// 没效果可使用try-catchwindow.webkit.messageHandlers.#OC方法名#.postMessage(#参数#)
回调方式分两种:delegate和target-action; 两种方式只能存一,优先delegate
- delegate方式,只要在控制器中公告
VDWebViewDelegate
中的方法
- (void)webView:(VDWebView *)webView didReceiveScriptMessage:(WKScriptMessage *)message;
- target-action方式
- 不能公告上述的代理商方法
- 在控制器(方法注册传入的scriptMessageHandler)中公告同名的OC方法
为什么要添加target-action的方式
target-action:目标-动作模式,拜C语言所赐,更是灵活很多,编译期没有任何检查,都是运行时的绑定
- 在
VDWebView
中就是通过NSSelectorFromString()
动态加载方法,再通过NSMethodSignature
和NSInvocation
进行方法的签名和调用 - 这样即可以充分的表现JS调用对应的OC方法一对一更加清晰并且方便解决
JS的调用和注入
可通过两种方式进行JS方法的调用,推荐第一种
- WKWebView的同名方法
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^)(id, NSError *))completionHandler;
- UIWebView的同名方法(不建议使用这个办法,由于会在内部等待执行结果)
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)javaScriptString;
脚本的注入和移除
/** 注入脚本(js...) @param source 注入的内容 @param injectionTime 注入时间 @param mainFrameOnly 只作用主框架 */- (void)addUserScriptWithSource:(NSString *)source injectionTime:(WKUserScriptInjectionTime)injectionTime forMainFrameOnly:(BOOL)mainFrameOnly;/** 移除所有注入的脚本 */- (void)removeAllUserScripts;
后续版本思考和设计中
- cookie的解决
- APP和web资源共享问题:比方图片
- 阻拦webView内部请求通过自己设置URL的方式进行JS交互
尾声
愿意理解或者者有任何问题的欢迎指教,有何不足多多担待!
说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » WKWebView的使用、优化和封装(VDWebView)
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » WKWebView的使用、优化和封装(VDWebView)