Swift iOS : WebView缓存图片的方法

广告

Swift iOS开发小书 ,帮你快速上手开发 www.ituring.com.cn/book/2413

正文

每次加载WebView内容,如果图片可以缓存的话,速度就会非常快。默认情况下,WebView自己来加载图片,缓存的策略也是自己定的。如想要自己缓存的话,那么可以使用URLSessionDataDelegate来截获HTTP访问,如果访问的是图片的话,就自己去发起请求,缓存,如果缓存了的话,就提取缓存,自己构建一个HTTP响应对象返回。

如下案例,使用了Kingfisher库做实际的图片缓存,从而隔离开和文件操作相关的细节。代码来自: github.com/Finb/V2ex-S… 。可以使用,但是代码有些破碎,晚点有时间才调整。

import UIKit
import Kingfisher
class Page: UIViewController,UIGestureRecognizerDelegate{var c : UIWebView!var tapGesture : UITapGestureRecognizer!override func viewDidLoad() {super.viewDidLoad()c = UIWebView()c.frame = super.view.frameview.addSubview(c)c.frame.origin.y += 100c.frame.size.height = 100c.frame.size.width = 100let button = UIButton()button.setTitle("reload", for: .normal)button.addTarget(self, action: #selector(tap), for: .touchDown)button.frame = CGRect(x: 0, y: 70, width: 100, height: 20)view.addSubview(button)}func tap(){loadurl()}func loadurl(){let url = URL(string:"https://httpbin.org/image/png")//must be a https url ,otherwise iOS will fobidden itlet ro = URLRequest(url:url!)c.loadRequest(ro)}
}
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {var window: UIWindow?func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {URLProtocol.registerClass(WebViewImageProtocol.self)self.window = UIWindow(frame: UIScreen.main.bounds)self.window!.rootViewController = Page()self.window?.makeKeyAndVisible()return true}
}
fileprivate let WebviewImageProtocolHandledKey = "WebviewImageProtocolHandledKey"class WebViewImageProtocol: URLProtocol ,URLSessionDataDelegate {var session: URLSession?var dataTask: URLSessionDataTask?var imageData: Data?override class func canInit(with request: URLRequest) -> Bool{let b = request.url?.absoluteURL.absoluteString.contains("png")if b! {if let tag = self.property(forKey: WebviewImageProtocolHandledKey, in: request) as? Bool , tag == true {return false}return true}return false}override class func canonicalRequest(for request: URLRequest) -> URLRequest{return request}override class func requestIsCacheEquivalent(_ a: URLRequest, to b: URLRequest) -> Bool {return super.requestIsCacheEquivalent(a, to: b)}override func startLoading() {let resource = ImageResource(downloadURL: self.request.url!)let data = try? Data(contentsOf:URL(fileURLWithPath: KingfisherManager.shared.cache.cachePath(forKey: resource.cacheKey)))if let data = data {//在磁盘上找到Kingfisher的缓存,则直接使用缓存print("hitted")var mimeType = data.contentTypeForImageData()mimeType.append(";charset=UTF-8")let header = ["Content-Type": mimeType,"Content-Length": String(data.count)]let response = HTTPURLResponse(url: self.request.url!, statusCode: 200, httpVersion: "1.1", headerFields: header)!self.client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .allowed)self.client?.urlProtocol(self, didLoad: data)self.client?.urlProtocolDidFinishLoading(self)}else{//没找到图片则下载print("caching")guard let newRequest = (self.request as NSURLRequest).mutableCopy() as? NSMutableURLRequest else {return}WebViewImageProtocol.setProperty(true, forKey: WebviewImageProtocolHandledKey, in: newRequest)self.session = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: nil)self.dataTask = self.session?.dataTask(with:newRequest as URLRequest)self.dataTask?.resume()}}override func stopLoading() {self.dataTask?.cancel()self.dataTask = nilself.imageData = nil}func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {self.client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .allowed)completionHandler(.allow)}func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {self.client?.urlProtocol(self, didLoad: data)if self.imageData == nil {self.imageData = data}else{self.imageData!.append(data)}}func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {if let error = error {self.client?.urlProtocol(self, didFailWithError: error)}else{self.client?.urlProtocolDidFinishLoading(self)let resource = ImageResource(downloadURL: self.request.url!)guard let imageData = self.imageData else { return }//保存图片到Kingfisherguard  let image = DefaultCacheSerializer.default.image(with: imageData, options: nil) else { return }KingfisherManager.shared.cache.store(image, original: imageData, forKey: resource.cacheKey,  toDisk: true){print("cached")}}}
}
fileprivate extension Data {func contentTypeForImageData() -> String {var c:UInt8 = 0self.copyBytes(to: &c, count: MemoryLayout<UInt8>.size * 1)switch c {case 0xFF:return "image/jpeg";case 0x89:return "image/png";case 0x47:return "image/gif";default:return ""}}
}复制代码

运行后点击按钮reload两次输出为:
caching
cached
hitted

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/257943.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux怎么同时查看两个文件,MultiTail - 在单个Linux终端中同时监视多个文件

无论是服务器管理员还是程序员&#xff0c;我们需要参考多个日志文件来有效地排除故障任务。 为了实现这一点&#xff0c;我们必须打开&#xff0c;拖尾或更少的不同shell中的每个日志文件。 但是&#xff0c;我们可以使用传统的tail命令状尾-f在/ var / log / messages文件或尾…

新一代蓝牙5标准开启 会成为物联网的最佳选择吗

在过去&#xff0c;蓝牙在生活中最常见的应用就是键盘、鼠标、音箱和蓝牙耳机&#xff0c;这些传输对频宽要求不高&#xff0c;蓝牙技术的采用不仅节省了线材成本&#xff0c;还增加了产品的灵活性。蓝牙技术联盟(SIG)正式宣布推出新一代标准蓝牙5(Bluetooth 5)&#xff0c;其主…

今日BBC

1、随身英语 Dry January 新年戒酒一个月 link 2、地道英语 Hot potato 棘手的问题“烫手山芋” link 3、今日新闻 Brussels attacks: Belgian police arrest six suspects link The arrests were made in the Schaerbeek district. There is no word yet on the identitie…

c语言中的指针语法,C语言中指针的用法介绍

C语言中指针的用法介绍for(int i0;i{num*s;s;}return num;)这个例子中的函数 fun统计一个字符串中各个字符的 ASCII 码值之和。前面说了&#xff0c;数组的名字也是一个指针。在函数调用中&#xff0c;当把 str 作为实参传递给形参 s后&#xff0c;实际是把 str 的值传递给了 s…

实验吧 貌似有点难 伪造ip

解题链接&#xff1a; http://ctf5.shiyanbar.com/phpaudit/ 解答&#xff1a; 点击View the source code —>代码显示IP为1.1.1.1即可得到KEY—>使用modify header伪造IP—>拿到flag 相关&#xff1a; modify header我也是第一次用&#xff0c;下面附上相关说明&…

用C语言用指针怎么算通用定积分,C语言:利用指针编写程序,用梯形法计算给定的定积分实例...

题目要求利用指针编写程序&#xff0c;用梯形法计算下列公式中的定积分&#xff1a;参考代码首先说明一下指针的用处&#xff1a;因为所传递的参数均为数字&#xff0c;并不需要使用指针提高效率&#xff0c;故这里使用指针指向函数。请注意calc()函数中的这一语句&#xff1a;…

单点登录系统cas资料汇总

http://jasig.github.io/cas/4.0.x/index.html 主页https://jasigcas.herokuapp.com demohttps://wiki.jasig.org/display/CASUM/Home 4.x之前的文档http://jasig.github.io/cas/4.1.x/index.html …

有限小数用c语言,分数化为有限小数或无限循环小数(c实现)

问题描述&#xff1a;将分数转化为小数&#xff0c;相信很多人都会吧&#xff0e;那么&#xff0c;这里给定一个分数N/D,N为分子&#xff0c;D为分母(N,D均为整数)&#xff0c;试编程求出N/D的小数形式&#xff0c;当然如果这个小数为无限循环小数&#xff0c;则把循环的部分用…

你该把前端外包出来了

2019独角兽企业重金招聘Python工程师标准>>> 移动热潮慢慢褪去&#xff0c;大的几个app已经霸占了所有的人桌面&#xff0c;而微信却变得越来越重要。微信里面&#xff0c;提倡H5的应用&#xff0c;H5应用开发成本低、上线快、易调整、跨平台等诸多优势&#xff0c;…

R 统计学工具部署和使用

由于公司内部对于市场数据分析的需求&#xff0c;要求引入R统计工具&#xff0c;并集成到报表工具中。对于R的介绍&#xff0c;大家请百度一下&#xff0c;当然&#xff0c;最好能去看官方的说明 https://www.r-project.org/ 下面简单介绍一下R工具的安装和数据分析工具Spotfir…

USACO Dual Palindromes

输出N个大于s的满足条件的数&#xff0c; 对于满足条件的数的定义是其2-10进制表示中&#xff0c;至少有两种表示为回文串。。还是暴力&#xff1a; /*ID: m1500293LANG: CPROG: dualpal */ #include <cstdio> #include <cstring> #include <algorithm>using…

c语言库函数fgets,C语言 标准I/O库函数 fgets 使用心得

char *fgets(char *s, int n, FILE *stream);参数说明&#xff1a;s --指定存放所读取的数据的位置n -- 指定所读取数据的最大长度(这个最大长度包括了字符串结束符 \0所占据的存储空间&#xff0c;因此&#xff0c;实际最大读取的有效字符数是 n - 1)stream --数据源&#xff…

Android下创建一个输入法

输入法是一种可以让用户输入文字的控件。Android提供了一套可扩展的输入法框架&#xff0c;使得应用程序可以让用户选择各种类型的输入法&#xff0c;比如基于触屏的键盘输入或者基于语音。当安装了特定输入法之后&#xff0c;用户即可在系统设置中选择个输入法&#xff0c;并在…

linux awk f,linux的awk详情(上)

一丶awk介绍AWK是一种处理文本文件的语言&#xff0c;是一个强大的文本分析工具&#xff0c;可以报告生成器&#xff0c;格式化文本输出1.常用语法awk [options] ‘program’ varvalue file…awk [options] -f programfile varvalue file…awk [options] BEGIN{ action;… } pa…

C#的async和await

C# 5.0中引入了async 和 await。这两个关键字可以让你更方便的写出异步代码。 看个例子&#xff1a; public class MyClass {public MyClass(){DisplayValue(); //这里不会阻塞System.Diagnostics.Debug.WriteLine("MyClass() End.");}public Task<double> Get…

eclipse创建android工程,在eclipse创建android 工程

1.在工具栏选择"New".在弹出对话框里&#xff0c;开打android文件夹&#xff0c;选择"android application Project"&#xff0c;选择“Next”.2.Application Name: 应用程序名称。Projetc Name: 工程名称。Packet Name: 包名称. 注意&#xff0c;包名称…

SQL select查询原理--查询语句执行原则转

1.单表查询&#xff1a;根据WHERE条件过滤表中的记录&#xff0c;形成中间表&#xff08;这个中间表对用户是不可见的&#xff09;&#xff1b;然后根据SELECT的选择列选择相应的列进行返回最终结果。 1)简单的单表查询 SELECT 字段 FROM 表名 WHERE 条件表达式 那它们是按什么…

android导航二级分类,Android实现腾讯新闻的新闻类别导航效果

效果图如下所示&#xff1a;1、在Adapter中加入如下代码private int clickTemp -1;//TODO 被选择的item下标/** * TODO 传入下标&#xff0c;设置被选择的item * * param position */public void setSelection(int position) {clickTemp position;}2、在Adapter的getView方法…

Linux下访问window挂载的磁盘

点击window挂在的磁盘,如下图左侧"文档". 出现如下错误: Error mounting /dev/sda3 .... Command-line mount -t "ntfs" -o "uhelperudisks2 修复办法: sudo ntfsfix /dev/sda6 参考资料: 1. win8安装ubuntu后不能访问windows其他磁盘转载于:https:…

linux遍历目录源代码

<pre code_snippet_id"1622396" snippet_file_name"blog_20160324_1_744516" name"code" class"cpp">遍历目录获取整个目录的占用空间: uint64_t dir_space(char *path) {int ret 0;uint64_t space 0;char cur_dir[PATH_MAX …