Kingfisher原理使用

今年到新公司,发现公司用的kingfisher这个第三方库,和SDWebImage很类似,不过是swift版本的,就了解了下。

源码地址: https://github.com/onevcat/Kingfisher

我看的是swift4.0最新版

 一、使用方式:

通过KingfisherManager单例对象调用。因为swift3以后大部分第三方调用普遍采用点方式,这个亦不例外,可以直接.kf调用单例。封装方式:

public final class Kingfisher<Base> {
    public let base: Base
    public init(_ base: Base) {
        self.base = base
    }
}

public protocol KingfisherCompatible {
    associatedtype CompatibleType
    var kf: CompatibleType { get }
}

public extension KingfisherCompatible {
    public var kf: Kingfisher<Self> {
        return Kingfisher(self)
    }
}

extension Image: KingfisherCompatible { }

extension ImageView: KingfisherCompatible { }
extension Button: KingfisherCompatible { }

 这样就可以实现image、Imageview、button的.kf调用,并且通过kf.base访问调用的对象实现封装。

通过扩展extension Kingfisher where Base: ImageView {}实现每个对象的自定义方法,方法内部self.base即当前imageView。

 let url = URL.init(string: newValue)
 self.imageView.kf.setImage(with: url)

基于kf作者imageView封装过后可以直接调用

二、下载原理:

KF是基于URLSession、URLSessionDelegate进行封装的,请求默认属性可以在appdeleget初始化是单例更改。例如:

KingfisherManager.shared.downloader.downloadTimeout = 12.0

更改超时时间

三、请求设置:

  1. 请求的默认设置方式通过上面的单例设置,单独每个请求的设置可以通过
retrieveImage(with resource: Resource,
        options: KingfisherOptionsInfo?,
        progressBlock: DownloadProgressBlock?,
        completionHandler: CompletionHandler?) -> RetrieveImageTask

单例方法调用的options设置,此外kf作者封装的也可以直接传参。

KingfisherOptionsInfo介绍:

  • case targetCache(ImageCache)//系统缓存位置。可以设置的属性
  • case originalCache(ImageCache)//系统缓存原始图像位置(只用于自己设置placeholder) 
  • case downloader(ImageDownloader)//获取更改session属性,设置请求

  • case transition(ImageTransition)//自定义动画

  • case downloadPriority(Float)//下载优先级(0-1)

  • case forceRefresh //每次请求忽略缓存,直接下载

  • case fromMemoryCacheOrRefresh//先取缓存再去文件,再去下载

  • forceTransition. //强制移动

  • cacheMemoryOnly  //只从缓存读取,不读取本机沙盒图片

  • onlyFromCache//从缓存、沙盒读取,没有也不下载网络,显示placeholder

  • backgroundDecode//设置后,显示前在后台线程解码

  • case scaleFactor(CGFloat)。//自定义图片data -> Image缩放比例,不指定按屏幕2x\3x缩放

  • preloadAllAnimationData////预先加载data成图片缓存

  • case requestModifier(ImageDownloadRequestModifier)//改变请求 func modified(for request: URLRequest) -> URLRequest?  //手动更改单个请求超时时间等一系列属性

  • case processor(ImageProcessor)//自定义da ta转图片样式

  • case cacheSerializer(CacheSerializer)//自定义缓存data 转图像样式

  • case keepCurrentImageWhileLoading //包含这个意味着placeHolder设置无效,没有直接用默认

  • case onlyLoadFirstFrame。//如果返回结果是.gif图,只取第一帧显示

  • cacheOriginalImage //设置后,同时缓存原始图片和下载后的图片

  • case callbackDispatchQueue(DispatchQueue?)。//自定义回掉队列,不设置默认主线程

四、缓存机制

//吐槽下,写了好久command+z一大片没了,好烦

缓存处理主要在ImageCache类里面

kf缓存和sdwebimage一致,默认存储在domain文件夹,都是下载下来存在缓存和沙盒里面。下载时先去缓存取,取不到取沙盒取,沙盒取不到去网络下载

此外,kf里面,每次进入后台都会删除一周以前的图片(默认一周),然后文件按存储日期排序,删除到自定义最大沙盒存储量的一半(默认无限制)

可以更改的属性(更改方式参考二三部分):

maxMemoryCost //最大缓存量(默认无限制,收到内存警告直接清空)

pathExtension   //沙盒后续拼接文件夹名称

maxCachePeriodInSecond. //清除多久前的图片,默认一周

maxDiskCacheSize //沙盒最大存储量,小于等于0表示无限制。默认无限制

五、下载设置

ImageDownloader这个文件里面(设置参考二三部分)

downloadTimeout. //超时时间

trustedHosts。//信任的请求地址,和自己实现请求代理设置冲突,二选一

sessionConfiguration。//session配置设置

requestsUsePipelining //请求是否管道类型,是否按顺序下载,第一个下载完成在下载下张图片。默认false

delegate. //下载代理,kf已经封装在请求代码块里面,也可以自己全局代理封装处理

authenticationChallengeResponder //信任请求代理,和trustedHosts冲突二选一

fetchLoads //下载完成每个URL可能有多个处理方式,优先取这里的。

六、其他

kf内图片处理挺好的,这里注释下部分方式,喜欢的可以自己去看下,在Image.swift文件里

1、扩展类存储属性,黑魔法:

 fileprivate(set) var animatedImageData: Data? {
        get {
            return objc_getAssociatedObject(base, &animatedImageDataKey) as? Data
        }
        set {
            objc_setAssociatedObject(base, &animatedImageDataKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }

2、public var normalized: Image   //返回调整后的图片

3、static func animated(with data: Data, scale: CGFloat = 1.0, duration: TimeInterval = 0.0, preloadAll: Bool, onlyFirstFrame: Bool = false) -> Image?   //GIF图data 转图片

4、static func image(data: Data, scale: CGFloat, preloadAllAnimationData: Bool, onlyFirstFrame: Bool) -> Image? //根据data生成图片,GIF图根据preloadAllAnimationData是否展示所有动画图片,onlyFirstFrame:是否只取GIF第一张图片 ,有调用上面的方法

5、public func image(withBlendMode blendMode: CGBlendMode,  alpha: CGFloat = 1, backgroundColor: Color? = nil)-> Image。   //根据blendMode、透明度、背景色 调整图片

6、public func image(withRoundRadius radius: CGFloat,  fit size: CGSize, roundingCorners corners: RectCorner = .all, backgroundColor: Color? = nil) -> Image ////切换到指定角度、大小、背景色

7、    public func resize(to size: CGSize) -> Image //改变图片大小

8、    public func resize(to size: CGSize, for contentMode: ContentMode) -> Image。//根据ContentMode和目标size更改图片大小。//aspectFit: 根据图片比缩小到size   // aspectFill:根据图片比放大到size

9、public func crop(to size: CGSize, anchorOn anchor: CGPoint) -> Image //固定瞄点,缩小图片到指定size

10、public func blurred(withRadius radius: CGFloat) -> Image//根据角度模糊处理图片

11、public func overlaying(with color: Color, fraction: CGFloat) -> Image//图片添加overlay覆盖色fraction覆盖透明度

12、public func adjusted(brightness: CGFloat, contrast: CGFloat, saturation: CGFloat, inputEV: CGFloat) -> Image//图片亮度、饱和度、对比度修改 kCIInputEVKey不知道这个对应什么描述,喜欢的可以自己看下效果。

13、public func scaled(to scale: CGFloat) -> Image//缩放‘

14、

//图片格式确定。根据前8个字节对比图片类型
    var imageFormat: ImageFormat {
        var buffer = [UInt8](repeating: 0, count: 8)
        (base as NSData).getBytes(&buffer, length: 8)
        if buffer == ImageHeaderData.PNG {
            return .PNG
        } else if buffer[0] == ImageHeaderData.JPEG_SOI[0] &&
            buffer[1] == ImageHeaderData.JPEG_SOI[1] &&
            buffer[2] == ImageHeaderData.JPEG_IF[0]
        {
            return .JPEG
        } else if buffer[0] == ImageHeaderData.GIF[0] &&
            buffer[1] == ImageHeaderData.GIF[1] &&
            buffer[2] == ImageHeaderData.GIF[2]
        {
            return .GIF
        }

        return .unknown
    }

   

   

   

猜你喜欢

转载自blog.csdn.net/wokuaab_q/article/details/81663311