namespacing kf 實現(xiàn)
引用文件:
- Kingfisher.swift
- ImageView+Kingfisher.swift
- UIButton+Kingfisher.swift
實現(xiàn):
//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
{
...
}
}
調(diào)用事例:
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 { }
定義協(xié)議 KingfisherCompatible窝稿,聲明屬性 kf,類型是范型 CompatibleType 寄疏。并要求遵守協(xié)議的一方,實現(xiàn)該屬性的 get 方法僵井。
在協(xié)議擴展中陕截,協(xié)議自身實現(xiàn)了屬性。這樣就不必在每個遵守該協(xié)議的類里實現(xiàn)該屬性了批什。參見蘋果文檔:
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.
協(xié)議里的 kf 是一個 Kingfisher 類的實例农曲,調(diào)用的方法是 Kingfisher 類的方法。根據(jù)類型的不同,調(diào)用不同類型里的方法乳规。如:對應(yīng) UIImageView / UIButton 的 Kingfisher 里的setImage 方法形葬。
綜上,也就實現(xiàn)了命名空間 kf 暮的。
如圖:
我們詳細說說 KingfisherCompatible 笙以。
public var kf: Kingfisher<Self>
: Self 用在協(xié)議里面,代表的是遵守協(xié)議的 對象(類/結(jié)構(gòu)體/枚舉) 類型冻辩。如:extension ImageView: KingfisherCompatible { }
猖腕,用在這里,Self 是 ImageView 恨闪; extension Button: KingfisherCompatible { }
倘感,用在這里, Self 是 Button 咙咽。
如果我們不用 public extension KingfisherCompatible
老玛,也可以在遵守協(xié)議的時候,單獨實現(xiàn) kf 屬性犁珠。
如單獨實現(xiàn) UIImageView 的協(xié)議擴展逻炊,像這樣:
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