WebView加载URL时webViewDidFinishLoad未触发问题求助
webViewDidFinishLoad不触发的问题 这个坑我之前做电商商品列表的时候踩过好几次!核心问题是WebKit的回调时机和CollectionView的Cell复用/数据源更新时机撞车了——当WebView刚加载完准备调用webViewDidFinishLoad时,对应的Cell可能已经被滚出屏幕复用掉,或者你已经更新了CollectionView的数据源,导致WebKit内部在处理回调时触发了数组越界的异常,被WebKit主动丢弃后,我们自己的webViewDidFinishLoad自然就得不到调用了。
给你几个亲测有效的解决方案:
给WebView绑定唯一标识,和Cell数据源强关联
在自定义CollectionViewCell里给WebView加个自定义属性,比如var targetURL: String?,加载请求前先把要加载的URL存到这个属性里。在webViewDidFinishLoad回调里,先对比当前WebView的targetURL和Cell当前绑定的数据源URL是否一致,如果不一致直接return,避免处理旧请求的回调。在回调前先验证Cell的有效性
当webViewDidFinishLoad触发时,先通过WebView的父视图找到对应的Cell,再用CollectionView的indexPath(for:)方法检查这个Cell是否还在可视范围内、是否有有效的indexPath:func webViewDidFinishLoad(_ webView: UIWebView) { guard let cell = webView.superview?.superview as? YourCustomCell, let indexPath = collectionView.indexPath(for: cell) else { return } // 确认数据源和当前Cell匹配后再执行后续逻辑 let currentData = yourDataSource[indexPath.row] if currentData.url == cell.targetURL { // 处理加载完成后的逻辑 } }在Cell复用的时候清理WebView状态
重写Cell的prepareForReuse方法,及时停止WebView的加载、清空代理,避免复用后的WebView继续触发旧回调:override func prepareForReuse() { super.prepareForReuse() webView.stopLoading() webView.navigationDelegate = nil // 清空WebView内容,避免显示旧页面 webView.loadHTMLString("", baseURL: nil) targetURL = nil }避免在WebView回调里直接操作CollectionView数据源
如果需要在加载完成后更新CollectionView,一定要先检查数据源的状态是否和当前WebView对应的数据一致,最好用DispatchQueue.main.async延迟一小段时间再执行刷新,给CollectionView的数据源更新留足时间。
这些方法的核心思路都是让WebView的回调逻辑和Cell的生命周期、数据源状态保持同步,从根源上避免触发WebKit内部的异常。
内容的提问来源于stack exchange,提问作者User511

