admin 管理员组文章数量: 1086019
IOS WebView 的返回缓存问题分析
相关工具
- IOS 模拟器
- Safari 调试器
问题描述
在一个结算列表页,发起审批流程,发起成功后再返回到该列表页,发现列表页的流程状态还是【未开始】, 这个涉及到了多项目间的跳转(甲方业务比较多,分项目开发会是一个趋势);另外,安卓没有这个问题
排查思路
按问题描述,操作一次,发现数据库状态已经改变, 但前端页面状态确实没变,刚开始以为是简单的 onLoad 和 onShow 问题。
实际上结算页和流程页实际是两个项目, 从流程项目返回结算项目后,不管页面请求写在 onLoad 还是 onShow 里,都应该会被重新执行才对; 可以从 Safari 中打开调试 WebView 的 inspector,来检查下前后端交互的过程
使用 location.reload()
重新加载页面, 可以看到应用和页面各自的日志(其中 page hide 是由 Vue 路由导航触发的), 操作发起审批,进入到流程项目
最后的 App Launch
和 App Show
便是流程项目的日志,再使用 history.go(-2)
返回结算列表页
可以看到,虽然页面返回了结算列表页,但是并没有打印预期的 load 和 show 日志, 这些方法走不进去,写在 onShow 里请求接口再刷新状态的逻辑也就不会执行; 接下来想办法解决问题,如果能从 Web 解决的话最好,可以避免 App 更新版本
打断点调试,能看到 uni-app 是通过监听 visibilitychange
事件,来触发的 onShow 和 onHide (其实 onShow 的调用方不只一个,比如首次加载时、页面回退时,都有相对应的逻辑,但跟此处关系不大)。
查找这个事件的相关资料时,看到也有尝试用 pageshow
1来解决其它类型的缓存问题,先用这个事件调试一下
测试以后,结果也不理想
从这个日志也能看出来,用 history.go(-2)
返回后,onLoad 方法确实没有触发, 但是 loaded 竟然又变成了 true (正常页面加载完以后,就把它变成了 false), 据此猜测,在离开一个系统时,IOS 把页面数据做了缓存,再返回这个页面时,又读取这些缓存做了渲染, 而且这种渲染不会触发上面的 visibilitychange
事件(dom api)事件, pageshow
(window api) 虽然可以触发, 但是考虑到需要发起审批流程的页面会越来越多,这种写法比较复杂, 如果其他开发人员也要修改这个页面的其它逻辑,很可能带来困扰, 就放弃了这个思路(另外开发时热加载的刷新逻辑和正常逻辑也不太一样,所以还需要再兼容考虑这种情况)
还是得回到从 IOS 层面解决缓存的思路上
- Data Store Record Types
- iOS - 清除Web界面的缓存
查找了一些资料后,判断这种情况可能是属于 WKWebsiteDataTypeMemoryCache(内存缓存), 刚好之前有调整过 WebView 的标题变化,凡是页面标题变化时,都会进入此方法, 便先把逻辑放在这里,经过验证,可以解决问题
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *, id> *)change context:(void *)context {if ([keyPath isEqualToString:@"title"]) {if (object == self.webView) {self.title = self.webView.title;// clear memory cacheNSSet *websiteDataTypes= [NSSet setWithArray:@[WKWebsiteDataTypeMemoryCache,]];NSDate *dateFrom = [NSDate dateWithTimeIntervalSince1970:0];[[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:websiteDataTypesmodifiedSince:dateFrom completionHandler:^{// doneNSLog(@"------------clear---------");}];} else {[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];}}
}
微调
考虑到其实只有跨系统的时候才需要清除缓存,而大多数情况可能只是在本系统内跳转, 所以上面这个清除时机也不合适,最后突然想到了 decidePolicyForNavigationAction
这个方法
经过简单验证,这个方法大致可以满足需求:单项目内的跳转不会触发这个方法, 而跳转到其它项目时会正常触发(也算 Vue 这类单页应用的前端路由特性), 所以便先把清除逻辑放在了这里面来解决问题
↩︎
本文标签: IOS WebView 的返回缓存问题分析
版权声明:本文标题:IOS WebView 的返回缓存问题分析 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.roclinux.cn/b/1693410084a220304.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论