Kingfisher 源码分析(一):命名空间 kf 实现

namespacing kf 实现

引用文件:

  • Kingfisher.swift
  • ImageView+Kingfisher.swift
  • UIButton+Kingfisher.swift

实现:

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

/**
 A type that has Kingfisher extensions.
 */
public protocol KingfisherCompatible {
    associatedtype CompatibleType
    var kf: CompatibleType { get }
}

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

extension Image: KingfisherCompatible { }
#if !os(watchOS)
extension ImageView: KingfisherCompatible { }
extension Button: KingfisherCompatible { }

//ImageView+Kingfisher.swift
extension Kingfisher where Base: ImageView {
@discardableResult
    public func setImage(with resource: Resource?,
                         placeholder: Image? = nil,
                         options: KingfisherOptionsInfo? = nil,
                         progressBlock: DownloadProgressBlock? = nil,
                         completionHandler: CompletionHandler? = nil) -> RetrieveImageTask
    {
        ...
    }
}

//UIButton+Kingfisher.swift
extension Kingfisher where Base: UIButton {
    @discardableResult
    public func setImage(with resource: Resource?,
                         for state: UIControlState,
                         placeholder: UIImage? = nil,
                         options: KingfisherOptionsInfo? = nil,
                         progressBlock: DownloadProgressBlock? = nil,
                         completionHandler: CompletionHandler? = nil) -> RetrieveImageTask
    {
        ...
    }
}

调用事例:

let imageView = UIImageView()
imageView.kf.setImage(...)

let button = UIButton()
button.kf.setImage(...)

分析

Kingfisher<Base> 是一个范型类,类型是 Base 。

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

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

定义协议 KingfisherCompatible,声明属性 kf,类型是范型 CompatibleType 。并要求遵守协议的一方,实现该属性的 get 方法。

在协议扩展中,协议自身实现了属性。这样就不必在每个遵守该协议的类里实现该属性了。参见苹果文档

Protocols can be extended to provide method and property implementations to conforming types. This allows you to define behavior on protocols themselves, rather than in each type’s individual conformance or in a global function.

协议里的 kf 是一个 Kingfisher 类的实例,调用的方法是 Kingfisher 类的方法。根据类型的不同,调用不同类型里的方法。如:对应 UIImageView / UIButton 的 Kingfisher 里的setImage 方法。

综上,也就实现了命名空间 kf 。

如图:

命名空间 kf

我们详细说说 KingfisherCompatible 。

public var kf: Kingfisher<Self> : Self 用在协议里面,代表的是遵守协议的 对象(类/结构体/枚举) 类型。如:extension ImageView: KingfisherCompatible { },用在这里,Self 是 ImageView ; extension Button: KingfisherCompatible { },用在这里, Self 是 Button 。

如果我们不用 public extension KingfisherCompatible ,也可以在遵守协议的时候,单独实现 kf 属性。

如单独实现 UIImageView 的协议扩展,像这样:

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

extension Kingfisher where Base: UIImageView  {
    public func setImage() { print("imageView setImage") }
}

最后,样例如下:

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 }
}
extension UIImageView: KingfisherCompatible {
    public var kf: Kingfisher<UIImageView> { return Kingfisher(self) }
}
extension Kingfisher where Base: UIImageView  {
    public func setImage() { print("imageView setImage") }
}
extension UIButton: KingfisherCompatible {
    public var kf: Kingfisher<UIButton> { return Kingfisher(self) }
}
extension Kingfisher where Base: UIButton {
    public func setImage() { print("button setImage") }
}

let imageView = UIImageView()
imageView.kf.setImage()
let button = UIButton()
button.kf.setImage()

//输出
imageView setImage
button setImage

推荐阅读更多精彩内容

  • 序言 Kingfisher是喵神的一个异步下载和缓存图片的Swift库,类似于OC 的SDWebImage中文简介...
    一口气全念完阅读 3,972评论 8 22
  • 晚风送来凉意细雨朦胧了橘黄色的灯光城市灯光慵懒的沉醉里笑容在每个人的脸上枯萎风声、雨声、鸣笛声不断被心灵的沉寂弹回...
    流水亦公子阅读 103评论 4 5
  • 旧友来探我在异乡清酌 如今烟不抽,没得借火 当年初学画 谈理想论美 囫囵宛若老虎吃猪 如今说 什么是美 好看的姑娘...
    鹿羊I阅读 21评论 0 2
  • 我们知道八字以月令取格,或月令所透之气取格发用。有的命局天干透出多种五行,所谓格取清为贵,比如透食神又透伤官为杂;...
    九龙居士_a337阅读 196评论 0 0
  • 第四卷 革命时期的爱情 第一到三章 我爬炉筒时,大概是九岁到十一二岁。到了四十岁上,我发现后来我干任何事情都没有了...
    吴玉纯阅读 61评论 0 0