swift3.0网络图片缓存原理简析

一. 缓存原理

图片缓存原理原理是,如内存没图片,去磁盘找,若磁盘也没有,则根据url去下载,然后缓存到内存和磁盘中,简单易用

缓存的目录结构如下图:

 //存储图片的文件夹
 var ljFilePath:String =NSHomeDirectory() +"/Documents/"+"LJImageCache/"

二. 图片名称处理

为了确保缓存下来的图片的唯一性,所以此处采用图片的url+md5=唯一标识符,来存储图片,如上图图片的名称。

创建一个Sting+MD5.swift字符串分类文件(同时此处需要创建一个bridge.h桥接文件,引入这个头文件

#import <CommonCrypto/CommonDigest.h>,md5加密方法需要使用的文件)

1.bridge.h桥接文件如下:

#ifndef bridge_h
#define bridge_h 

#import <CommonCrypto/CommonDigest.h> 

#endif /* bridge_h */

2. Sting+MD5.swift文件如下

import Foundation 

extension String {
  var md5 : String{
    let str = self.cString(using: String.Encoding.utf8)
    let strLen = CC_LONG(self.lengthOfBytes(using: String.Encoding.utf8))
    let digestLen = Int(CC_MD5_DIGEST_LENGTH)
    let result = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: digestLen) 

    CC_MD5(str!, strLen, result) 

    let hash = NSMutableString()
    for i in 0 ..< digestLen {
      hash.appendFormat("%02x", result[i])
    }
    result.deinitialize() 

    return String(format: hash as String)
  }
}

三.图片缓存和读取

1. 图片缓存

func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
  {
    if ljcallBackClosure != nil ,let data = self.responseData{
      weak var weakSelf : LJOpreationManager? = self
      DispatchQueue.main.async
      {
        print("URLSessionDataDelegate----数据下载完毕") 

        LJCacheDataManage.shared.setMemoryCache((task.currentRequest?.url?.absoluteString)!,data as Data) 

        //图片缓存,根据唯一的url来作为存储数据的名称
        let a = LJFileManager.shared.writeFile((task.currentRequest?.url?.absoluteString)!,data as NSData) 

        print("-----写入文件成功\(a)") 

        //将接收的数据结果回调到前台,用于进度展示
        weakSelf?.ljcallBackClosure!(data as Data ,nil)
      }
    }
  } 

2.图片读取

public func retrieveImage(_ ljurl: String, _ ljcallback: @escaping OpreationClosure){ 

    if ljurl != "" { 

      if LJFileManager.shared.readFileFromCache(ljurl) != nil {
        //将接收的数据结果回调到前台,用于进度展示
        print("获取的是Disk缓存数据哦完毕")
        ljcallback(LJFileManager.shared.readFileFromCache(ljurl) as! Data,nil)
      }
      //首先取缓存数据,没取到的话,直接下载
     else if LJCacheDataManage.shared.getMemoryCache(ljurl) != nil {
        //将接收的数据结果回调到前台,用于进度展示
        print("获取的是Memory缓存数据哦完毕")
        ljcallback(LJCacheDataManage.shared.getMemoryCache(ljurl) ,nil)
      }
      else
      {
       _ = self.requestWebByUrl(ljurl, ljcallback)
      }
    }
  } 

3. 读写磁盘文件

(1)存储的时候给url进行md5加密得到fileName.md5文件名称,然后存储,如上面的截图

(2)读取文件时,给url进行md5加密得到path.md5的,然后获取文件数据

/* 写文件
  fileName: 文件名称
  data: 数据data
*/
func writeFile(_ fileName:String , _ data:NSData) -> Bool{ 

  //let filePath:String = NSHomeDirectory() + "/Documents/" + fileName.md5
  //return data.write(toFile: filePath, atomically: true)
  guard self.isExistFileDir(ljFilePath) else{
    return false
  } 

  guard let filePath : String = ljFilePath + fileName.md5 else{
    return false
  }
  return data.write(toFile: filePath, atomically: true)
} 

//读取文件 -(根据路径)
func readFileFromCache(_ path:String) -> NSData?{ 

  if self.isExistFileDir(ljFilePath)
  {
    let ljpatch = ljFilePath + path.md5
    var result:NSData?
    do{
      result = try NSData(contentsOfFile: ljpatch, options: Data.ReadingOptions.uncached)
    }catch{
      return nil
    }
    return result
  }
  return nil
} 

4.读写内存文件

import Foundation 

class LJCacheDataManage: NSObject{ 

  //单例
  public static let shared = LJCacheDataManage() 

  // public var diskCache = 

  //缓存的数据
  public var memoryCache = Dictionary<String, Data>() 

  //返回缓存的数据
  func getMemoryCache(_ urlStr : String) -> Data? { 

    print("返回缓存的数据------\(memoryCache[urlStr] ?? nil)")
    return (memoryCache[urlStr] ?? nil)
  } 

  //设置缓存值
  func setMemoryCache(_ urlStr : String, _ data : Data){
    if urlStr != "", data != nil {
      memoryCache[urlStr] = data
    }
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 详解Swift中对C语言接口缓存的使用以及数组与字符串转为指针类型的方法

    详解Swift中对C语言接口缓存的使用以及数组与字符串转为指针类型的方法 由于Swift编程语言属于上层编程语言,而Swift中由于为了低层的高性能计算接口,所以往往需要C语言中的指针类型,由此,在Swift编程语言刚诞生的时候就有了UnsafePointer与UnsafeMutablePointer类型,分别对应为const Type*类型与Type *类型. 而在Swift编程语言中,由于一般数组(Array)对象都无法直接用于C语言中含有指针类型的函数参数(比如:void*),所以往往需要

  • swift3.0网络图片缓存原理简析

    一. 缓存原理 图片缓存原理原理是,如内存没图片,去磁盘找,若磁盘也没有,则根据url去下载,然后缓存到内存和磁盘中,简单易用 缓存的目录结构如下图: //存储图片的文件夹 var ljFilePath:String =NSHomeDirectory() +"/Documents/"+"LJImageCache/" 二. 图片名称处理 为了确保缓存下来的图片的唯一性,所以此处采用图片的url+md5=唯一标识符,来存储图片,如上图图片的名称. 创建一个Sting+M

  • JavaScript mapreduce工作原理简析

    谷歌在2003到2006年间连续发表了三篇非常有影响力的文章,分别是2003年在SOSP上发布的GFS,2004年在OSDI上发布的MapReduce,以及2006年在OSDI上发布的BigTable.GFS是文件系统相关的,其对后来的分布式文件系统设计具有指导意义:MapReduce是一种并行计算的编程模型,用于作业调度:BigTable是一个用于管理结构化数据的分布式存储系统,构建在GFS.Chubby.SSTable等Google技术之上.相当多的Google应用使用了这三种技术,比如Go

  • Vue实现virtual-dom的原理简析

    virtual-dom(后文简称vdom)的概念大规模的推广还是得益于react出现,virtual-dom也是react这个框架的非常重要的特性之一.相比于频繁的手动去操作dom而带来性能问题,vdom很好的将dom做了一层映射关系,进而将在我们本需要直接进行dom的一系列操作,映射到了操作vdom,而vdom上定义了关于真实dom的一些关键的信息,vdom完全是用js去实现,和宿主浏览器没有任何联系,此外得益于js的执行速度,将原本需要在真实dom进行的创建节点,删除节点,添加节点等一系列复

  • H2 数据库导入CSV文件实现原理简析

    1.启动H2数据库不打开浏览器窗口(默认是打开的) 2.数据库创建SQL增加了支持BigDecimal类型,h2数据库默认是不支持bigdecimal类型的: Sql代码 复制代码 代码如下: create table test(id int(11),charge BigDecimal(12)) Sql代码 复制代码 代码如下: create table test(id int(11),charge BigDecimal(12)) 3.通过传参数方式导入数据库脚本 复制代码 代码如下: new

  • Vue-cli@3.0 插件系统简析

    Vue-cli@3.0 是一个全新的 Vue 项目脚手架.不同于 1.x/2.x 基于模板的脚手架,Vue-cli@3.0 采用了一套基于插件的架构,它将部分核心功能收敛至 CLI 内部,同时对开发者暴露可拓展的 API 以供开发者对 CLI 的功能进行灵活的拓展和配置.接下来我们就通过 Vue-cli@3.0 的源码来看下这套插件架构是如何设计的. 整个插件系统当中包含2个重要的组成部分: @vue/cli,提供 cli 命令服务,例如vue create创建一个新的项目: @vue/cli-

  • Vue数据绑定简析小结

    作为MVVM框架的一种,Vue最为人津津乐道的当是数据与视图的绑定,将直接操作DOM节点变为修改 data 数据,利用 Virtual Dom 来 Diff 对比新旧视图,从而实现更新.不仅如此,还可以通过 Vue.prototype.$watch 来监听 data 的变化并执行回调函数,实现自定义的逻辑.虽然日常的编码运用已经驾轻就熟,但未曾去深究技术背后的实现原理.作为一个好学的程序员,知其然更要知其所以然,本文将从源码的角度来对Vue响应式数据中的观察者模式进行简析. 初始化 Vue 实例

  • 简析Linux网络编程函数

    目录 1,创建套接字socket 2,绑定套接字bind 3,创建监听:listen 4,等待连接accept 5, 收发消息send和recv 6,关闭套接字描述符close 7,基于tcp协议的C/S服务器模型 8,实现代码 网络编程的一些基本函数:也是实现tcp协议通讯的基本步骤,实现代码在最后,IP需要修改为自己的IP,即可通信: 1,创建套接字socket 函数原型: #include<sys/types.h> #include<sys/socket.h> int soc

  • Python函数式编程之面向过程面向对象及函数式简析

    目录 Python 函数式编程 同一案例的不同写法,展示函数式编程 面向过程的写法 面向对象的写法 接下来进入正题,函数式编程的落地实现 Python 函数式编程的特点 纯函数 Python 函数式编程 Python 不是纯粹的函数式语言,但你可以使用 Python 进行函数式编程 典型的听君一席话,如听一席话,说白了就是 Python 具备函数式编程的特性, so,可以借用函数式语言的设计模式和编程技术,把代码写成函数式编程的样子 一般此时我会吹嘘一下,函数式代码比较简洁和优雅~ 好了,已经吹

  • C语言简析指针用途

    目录 对象的访问方式 什么是指针 指针变量 与指针相关的运算符 指针变量作为函数参数 数组与指针 多维数组与指针 指针常量 和 常量指针 指针数组 与 数组指针 字符串与指针 函数指针 二级指针 与 多级指针 在C语言中,任何一个变量,都有两层含义: (1) 代表该变量的存储单元的地址:变量的地址 左值 lvalue (2) 代表该变量的值:右值 rvalue 对于一个变量的访问,只有两种情况: 一是把一个值写到变量的地址中去 (lvalue) 二是从变量的地址中取变量的值 (rvalue) 对

  • Mysql中FIND_IN_SET()和IN区别简析

    前段时间项目中使用到Mysql的FIND_IN_SET函数,感觉挺好用的.过一段时间,老大找到我说,这个需要改为IN,哈哈,只能改了,原因会在下面分析到! 弄个测试表来说说两者的区别,测试数据直接在问答区copy一份,能说明问题就行,哈哈,如果侵犯您的版权还请见谅,互联网吗,就需要分享! 测试代码: CREATE TABLE `test` ( `id` int(8) NOT NULL auto_increment, `name` varchar(255) NOT NULL, `list` var

随机推荐