iOS中如何在UIWebView/WKWebView加载动效WebP图片?
iOS WebView加载动效WebP图片解决方案
刚踩过类似的坑,来给你梳理下可行的实现方案,分两种核心场景(推荐的WKWebView和已弃用的UIWebView)来说:
一、优先推荐:WKWebView 方案
苹果从iOS 14开始,WKWebView原生支持静态和动效WebP,但需要注意几个配置细节,尤其是本地HTML和远程资源的加载逻辑:
1. iOS 14+ 原生支持(无需第三方库)
如果你的App只适配iOS14及以上,那步骤非常简洁:
- 对于本地HTML:确保WebP图片和HTML文件放在同一个Bundle目录下,HTML里直接用相对路径引用即可,比如:
加载本地HTML时,要正确设置允许访问的目录:<img src="./bored_animation.webp" alt="Animated WebP">if let htmlURL = Bundle.main.url(forResource: "index", withExtension: "html") { let accessDir = htmlURL.deletingLastPathComponent() webView.loadFileURL(htmlURL, allowingReadAccessTo: accessDir) } - 对于远程WebP(比如你提供的Cloudinary链接):需要让WebView允许动效自动播放,在WKWebViewConfiguration里添加配置:
这样动效WebP就能像GIF一样自动循环播放了。let config = WKWebViewConfiguration() config.allowsInlineMediaPlayback = true config.mediaTypesRequiringUserActionForPlayback = .none let webView = WKWebView(frame: view.bounds, configuration: config)
2. 兼容iOS 14以下版本
如果需要适配更低版本,就得借助第三方库解码WebP,推荐用SDWebImageWebPCoder(SDWebImage的官方WebP扩展),核心思路是拦截WebP请求,解码后转成WebView支持的格式(比如GIF)再返回:
步骤1:集成依赖
在Podfile里添加:
pod 'SDWebImageWebPCoder'
执行pod install完成集成。
步骤2:自定义Scheme拦截WebP请求
给WKWebView注册自定义scheme(比如webp://),然后拦截请求并解码:
class WebPWebViewController: UIViewController, WKURLSchemeHandler { private var webView: WKWebView! override func viewDidLoad() { super.viewDidLoad() setupWebView() loadLocalHTML() } private func setupWebView() { let config = WKWebViewConfiguration() // 注册自定义scheme处理WebP config.setURLSchemeHandler(self, forURLScheme: "webp") webView = WKWebView(frame: view.bounds, configuration: config) view.addSubview(webView) } private func loadLocalHTML() { guard let htmlURL = Bundle.main.url(forResource: "index", withExtension: "html") else { return } let accessDir = htmlURL.deletingLastPathComponent() webView.loadFileURL(htmlURL, allowingReadAccessTo: accessDir) } // MARK: - WKURLSchemeHandler func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) { guard let url = urlSchemeTask.request.url, url.scheme == "webp" else { urlSchemeTask.didFailWithError(NSError(domain: "WebPHandler", code: -1, userInfo: [NSLocalizedDescriptionKey: "无效的Scheme"])) return } // 从Bundle获取WebP文件 let fileName = url.path.trimmingCharacters(in: ["/"]) guard let webPURL = Bundle.main.url(forResource: fileName, withExtension: "webp") else { urlSchemeTask.didFailWithError(NSError(domain: "WebPHandler", code: -2, userInfo: [NSLocalizedDescriptionKey: "WebP文件不存在"])) return } do { let webpData = try Data(contentsOf: webPURL) // 解码动效WebP let coder = SDImageWebPCoder.shared let options = [SDImageCoderOption.webpAllowAnimation: true] as [SDImageCoderOption: Any] guard let animatedImage = coder?.decodedImage(with: webpData, options: options) else { urlSchemeTask.didFailWithError(NSError(domain: "WebPHandler", code: -3, userInfo: [NSLocalizedDescriptionKey: "WebP解码失败"])) return } // 转成GIF格式返回给WebView guard let gifData = animatedImage.sd_imageData(as: .gif) else { urlSchemeTask.didFailWithError(NSError(domain: "WebPHandler", code: -4, userInfo: [NSLocalizedDescriptionKey: "转GIF失败"])) return } let response = URLResponse(url: url, mimeType: "image/gif", expectedContentLength: gifData.count, textEncodingName: nil) urlSchemeTask.didReceive(response) urlSchemeTask.didReceive(gifData) urlSchemeTask.didFinish() } catch { urlSchemeTask.didFailWithError(error) } } func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) { // 可选:处理请求取消逻辑 } }
步骤3:修改本地HTML的图片引用
把原来的WebP路径改成自定义scheme的格式:
<img src="webp://bored_animation" alt="Animated WebP">
二、UIWebView 方案(不推荐,已被苹果弃用)
如果还在维护旧项目使用UIWebView,同样可以用SDWebImageWebPCoder处理,核心是通过UIWebViewDelegate拦截WebP请求:
class UIWebPWebViewController: UIViewController, UIWebViewDelegate { private var webView: UIWebView! override func viewDidLoad() { super.viewDidLoad() webView = UIWebView(frame: view.bounds) webView.delegate = self view.addSubview(webView) // 加载本地HTML if let htmlPath = Bundle.main.path(forResource: "index", ofType: "html") { let htmlString = try? String(contentsOfFile: htmlPath, encoding: .utf8) webView.loadHTMLString(htmlString ?? "", baseURL: Bundle.main.bundleURL) } } // MARK: - UIWebViewDelegate func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebView.NavigationType) -> Bool { guard let url = request.url, url.pathExtension.lowercased() == "webp" else { return true } // 加载并解码WebP if let webpData = try? Data(contentsOf: url), let coder = SDImageWebPCoder.shared, let animatedImage = coder.decodedImage(with: webpData, options: [.webpAllowAnimation: true]), let gifData = animatedImage.sd_imageData(as: .gif) { // 加载转换后的GIF数据 webView.load(gifData, mimeType: "image/gif", textEncodingName: "utf-8", baseURL: url.deletingLastPathComponent()) return false } return true } }
注意事项
- 本地资源要确保添加到Xcode的Target中,勾选"Copy Bundle Resources";
- 远程WebP要注意App Transport Security(ATS)设置,若链接是HTTP需要在Info.plist中添加例外;
- 尽量迁移到WKWebView,UIWebView已被苹果弃用,不再接收安全更新。
内容的提问来源于stack exchange,提问作者Rameshios
相关产品推荐
相关产品推荐

