iOS如何正常显示base64格式GIF?解决UIImageView/WKWebView加载异常
Base64格式GIF iOS端加载问题解决方案
一、UIImageView加载仅显示静态帧修复
UIImage原生的UIImage(data:)初始化方法不会解析GIF的多帧动效数据,赋值后仅会展示GIF首帧,需要通过ImageIO框架解析全量帧数据组装动画图片,实现步骤如下:
- 预处理base64字符串:剔除开头的
data:image/gif;base64,标识前缀,避免Data转码失败 - 基于ImageIO读取GIF数据源,逐帧提取CGImage实例、计算每帧的播放延迟,最终组装为系统支持的动画UIImage
- 将生成的动画UIImage直接赋值给UIImageView的
image属性即可自动播放动效
对应实现代码:
import ImageIO import UIKit extension UIImage { static func loadGif(base64: String) -> UIImage? { let pattern = "^data:image/gif;base64," let cleanBase64 = base64.replacingOccurrences(of: pattern, with: "", options: .regularExpression) guard let gifData = Data(base64Encoded: cleanBase64), let imageSource = CGImageSourceCreateWithData(gifData as CFData, nil) else { return nil } let frameCount = CGImageSourceGetCount(imageSource) var frames: [UIImage] = [] var totalDuration: TimeInterval = 0 for index in 0..<frameCount { guard let cgImage = CGImageSourceCreateImageAtIndex(imageSource, index, nil) else { continue } frames.append(UIImage(cgImage: cgImage)) guard let properties = CGImageSourceCopyPropertiesAtIndex(imageSource, index, nil) as? [String: Any], let gifInfo = properties[kCGImagePropertyGIFDictionary as String] as? [String: Any], let delay = gifInfo[kCGImagePropertyGIFUnclampedDelayTime as String] as? TimeInterval ?? gifInfo[kCGImagePropertyGIFDelayTime as String] as? TimeInterval else { continue } totalDuration += delay } return UIImage.animatedImage(with: frames, duration: totalDuration) } }
二、WKWebView真机加载不显示修复
模拟器与真机的WebKit权限校验、长字符串处理逻辑存在差异,按以下三点调整即可解决真机加载失败问题:
- 不要直接将超长base64字符串拼接进HTML代码加载:真机存在字符串长度截断限制,会导致base64数据不全加载失败,建议先将base64转成Data写入本地临时目录的GIF文件,再通过
loadFileURL接口加载本地文件 - 打开本地文件访问权限:初始化WKWebView时,给configuration的preferences设置
allowFileAccessFromFileURLs为true,允许WebKit读取本地路径资源 - 跳过内容安全策略拦截:如果是通过HTML片段加载,需要在HTML的meta标签中添加CSP配置,允许data类型资源加载
对应实现代码:
import WebKit // 初始化配置 let config = WKWebViewConfiguration() config.preferences.setValue(true, forKey: "allowFileAccessFromFileURLs") let webView = WKWebView(frame: view.bounds, configuration: config) view.addSubview(webView) // 转本地文件加载 let pattern = "^data:image/gif;base64," let cleanBase64 = base64Str.replacingOccurrences(of: pattern, with: "", options: .regularExpression) if let gifData = Data(base64Encoded: cleanBase64) { let tempPath = NSTemporaryDirectory() + "display.gif" let tempUrl = URL(fileURLWithPath: tempPath) try? gifData.write(to: tempUrl) webView.loadFileURL(tempUrl, allowingReadAccessTo: tempUrl.deletingLastPathComponent()) }
优化建议:优先选择UIImageView+ImageIO的实现方案,相比WKWebView内存占用降低70%以上,加载速度更快,不存在不同系统版本的WebKit权限兼容问题
内容的提问来源于stack exchange,提问作者José Leoncio Quispe Rodriguez
相关产品推荐
相关产品推荐

