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.pswp.cn/news/257943.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/257943.shtml
英文地址,請注明出處:http://en.pswp.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 …