WKWebView加载时Loading动画卡顿问题求助
解决WKWebView加载时动画卡顿的问题
我来帮你分析下问题根源,然后给出具体的修复方案:
问题原因拆解
- 线程错误:你在Alamofire的响应闭包中直接调用
webView.load(),但Alamofire的响应闭包默认运行在后台队列,在后台线程操作UI组件(WKWebView)会导致主线程阻塞,直接让加载动画卡顿。 - 不可靠的结束时机:依赖JS发送
loading-finished事件来隐藏动画的方式不够稳定,如果JS事件延迟或失败,动画会一直挂着,也可能间接加重线程冲突。
具体修复步骤
1. 强制UI操作在主线程执行
修改Alamofire的请求逻辑,把webView.load()的调用切换到主线程,同时加上错误处理:
func loadWebview(){ Loading.shared.show(self.view) Alamofire.request(MYAPI, method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: nil) .responseJSON { response in // 切换到主线程处理UI操作 DispatchQueue.main.async { // 处理请求失败的情况 guard let responseData = response.result.value as? [String: Any], let key = responseData["key"] as? String else { Loading.shared.hide(animated: true) return } // 构造URL并加载 guard let url = URL(string: "https://path-to-load/\(key)") else { Loading.shared.hide(animated: true) return } self.webView!.load(URLRequest(url: url)) } } }
2. 用WKNavigationDelegate监听加载状态(替代JS事件)
通过系统代理方法捕获WKWebView的加载完成时机,比JS事件更可靠:
首先在viewDidLoad中设置代理:
override func viewDidLoad() { super.viewDidLoad() webView = WKWebView(frame: webViewContainer.bounds, configuration: webConfig) webView!.autoresizingMask = [.flexibleWidth, .flexibleHeight] webView?.scrollView.isScrollEnabled = false // 添加导航代理设置 webView?.navigationDelegate = self webViewContainer.addSubview(webView!) loadWebview() }
然后实现代理方法:
extension MyViewController: WKNavigationDelegate { // 页面加载完成时触发 func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { Loading.shared.hide(animated: true) } // 可选:处理加载失败的场景 func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) { Loading.shared.hide(animated: true) // 这里可以添加错误提示逻辑 } }
3. 确保Loading类的UI操作全在主线程
修改Loading的show方法,把所有UI相关操作包在主线程里,避免线程冲突:
public func show(_ view: UIView, inView: Bool = false) { DispatchQueue.main.async { [weak self] in guard let self = self else { return } var window: UIView! if inView == false, let w = view.window { window = w } else { window = view } if self.blurredEffectView.superview == window { return } // 先移除旧动画,避免重复添加 self.imageView.layer.removeAnimation(forKey: "rotationAnimation") // 创建旋转动画 let rotation: CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z") rotation.toValue = NSNumber(value: Double.pi * 2) rotation.duration = 1 rotation.isCumulative = true rotation.repeatCount = Float.greatestFiniteMagnitude self.imageView.layer.add(rotation, forKey: "rotationAnimation") // 布局动画视图 self.imageView.center = window.center self.blurredEffectView.frame = window.bounds window.addSubview(self.blurredEffectView) self.blurredEffectView.fadeIn() } }
额外优化建议
- 给Loading类的
hide方法也加上主线程包裹,确保淡出动画流畅执行; - 可以给Loading添加一个
isShowing状态标记,避免重复调用show方法导致动画叠加。
这样修改后,加载动画会在WKWebView整个加载过程中持续流畅转动,直到页面加载完成(或失败)才会自动隐藏,彻底解决卡顿问题。
内容的提问来源于stack exchange,提问作者denis_lor
相关产品推荐
相关产品推荐

