Kingfisher使用备忘录

简单使用

let url = URL(string: "https://domain.com/image.jpg")!
imageView.kf.setImage(with: url)

传入url即可。Kingfisher会尝试从缓存中获取图像,如果找不到,才回去下载,然后缓存使用。缓存的key是url的absoluteString。

指定缓存键

let resource = ImageResource(downloadURL: url, cacheKey: "my_cache_key")
imageView.kf.setImage(with: resource)

如果想自定义缓存key,可以这样做。

使用占位图像

let image = UIImage(named: "default_profile_icon")
imageView.kf.setImage(with: url, placeholder: image)

可以自定义占位图像。当然,也可以自定义UIView为占位视图,只需要该视图遵循Placeholder即可。

class MyView: UIView { /* Your implementation of view */ }

extension MyView: Placeholder { /* Just leave it empty */}

imageView.kf.setImage(with: url, placeholder: MyView())

使用完成后的闭包

imageView.kf.setImage(with: url, completionHandler: { 
(image, error, cacheType, imageUrl) in
// image: Image? `nil` means failed
// error: NSError? non-`nil` means failed
// cacheType: CacheType
//                  .none - Just downloaded
//                  .memory - Got from memory cache
//                  .disk - Got from disk cache
// imageUrl: URL of the image
})

下载完成或者发生错误后,会调用该闭包。

下载时带有指示器

imageView.kf.indicatorType = .activity
imageView.kf.setImage(with: url)

会带有下载指示器

下载时使用自定义的GIF文件或者任何图像作为指示图像

let p = Bundle.main.path(forResource: "loader", ofType: "gif")!
let data = try! Data(contentsOf: URL(fileURLWithPath: p))

imageView.kf.indicatorType = .image(imageData: data)

imageView.kf.setImage(with: url)

使用自定义视图指示

struct MyIndicator: Indicator {
let view: UIView = UIView()

func startAnimatingView() { view.isHidden = false }
func stopAnimatingView() { view.isHidden = true }

init() {
view.backgroundColor = .red
}
}

let i = MyIndicator()
imageView.kf.indicatorType = .custom(indicator: i)

使用进度模块更新自己的指示UI

imageView.kf.setImage(with: url, progressBlock: {
receivedSize, totalSize in
let percentage = (Float(receivedSize) / Float(totalSize)) * 100.0
print("downloading progress: \(percentage)%")
myIndicator.percentage = percentage
})

下载后设置图像时添加淡入淡出过渡

imageView.kf.setImage(with: url, options: [.transition(.fade(0.2))])

在显示和缓存前将下载的图像转换成圆角

let processor = RoundCornerImageProcessor(cornerRadius: 20)
imageView.kf.setImage(with: url, placeholder: nil, options: [.processor(processor)])

可以定义成其他效果,比如模糊,色调,黑白等

设置图像之前应用多个处理

let processor = BlurImageProcessor(blurRadius: 4) >> RoundCornerImageProcessor(cornerRadius: 20)
imageView.kf.setImage(with: url, placeholder: nil, options: [.processor(processor)])

跳过缓存搜索,强制下载图像

imageView.kf.setImage(with: url, options: [.forceRefresh])

只搜索缓存中的图片,不存在也不下载

imageView.kf.setImage(with: url, options: [.onlyFromCache])

应用在UIButton和NSButton上时

let uiButton: UIButton = //...
uiButton.kf.setImage(with: url, for: .normal, placeholder: nil, options: nil, progressBlock: nil, completionHandler: nil)
uiButton.kf.setBackgroundImage(with: url, for: .normal, placeholder: nil, options: nil, progressBlock: nil, completionHandler: nil)

let nsButton: NSButton = //...
nsButton.kf.setImage(with: url, placeholder: nil, options: nil, progressBlock: nil, completionHandler: nil)
nsButton.kf.setAlternateImage(with: url, placeholder: nil, options: nil, progressBlock: nil, completionHandler: nil)

缓存和下载器

Kingfisher由两个主要组件组成:一个ImageDownloader用于下载图像,一个ImageCache用于处理缓存。你可以单独使用它们中的任何一个。

使用ImageDownloader下载的图像没有被缓存

ImageDownloader.default.downloadImage(with: url, options: [], progressBlock: nil) {
(image, error, url, data) in
print("Downloaded Image: \(image)")
}

使用ImageCache存储或获取图像

let image: UIImage = //...
ImageCache.default.store(image, forKey: "key_for_image")

let anotherImage: UIImage = //...
let imageData = //.. Data from anotherImage
ImageCache.default.store(anotherImage, 
original: imageData, 
forKey: "key_for_another_image", 
toDisk: false)

ImageCache.default.isImageCached(forKey: "key_for_image")
// (cached: true, cacheType: .memory)
ImageCache.default.isImageCached(forKey: "key_for_another_image")
// (cached: true, cacheType: .memory)

// Force quit and relaunch
ImageCache.default.isImageCached(forKey: "key_for_image")
// (cached: true, cacheType: .disk)
ImageCache.default.isImageCached(forKey: "key_for_another_image")
// (cached: false, cacheType: .none)

ImageCache.default.retrieveImage(forKey: "key_for_image", options: nil) { 
image, cacheType in
if let image = image {
print("Get image \(image), cacheType: \(cacheType).")
//In this code snippet, the `cacheType` is .disk
} else {
print("Not exist in cache.")
}
}

删除缓存图像

// From both memory and disk
ImageCache.default.removeImage(forKey: "key_for_image")

// Only from memory
ImageCache.default.removeImage(forKey: "key_for_image", fromDisk: false)

设置缓存磁盘大小

// 50 MB
ImageCache.default.maxDiskCacheSize = 50 * 1024 * 1024
// Default value is 0, which means no limit.

默认使用default

获取已用磁盘大小

ImageCache.default.calculateDiskCacheSize { size in
print("Used disk size by bytes: \(size)")
}

手动清除缓存

// Clear memory cache right away.
cache.clearMemoryCache()

// Clear disk cache. This is an async operation.
cache.clearDiskCache()

// Clean expired or size exceeded disk cache. This is an async operation.
cache.cleanExpiredDiskCache()

收到内存警告时,会清除内存中的缓存,并且清理过期的和超出尺寸的缓存,通常不需要手动清理。

设置缓存保持时间

// 3 days
ImageCache.default.maxCachePeriodInSecond = 60 * 60 * 24 * 3
// Default value is 60 * 60 * 24 * 7, which means 1 week.

设置-1表示永不过期

为缓存文件添加后缀

// Set a default path extension
KingfisherManager.shared.cache.pathExtension = "jpg"

为图片下载器设置超时时间

// 30 second
ImageDownloader.default.downloadTimeout = 30.0
// Default value is 15.

使用自定义的下载器和缓存

let downloader = ImageDownloader(name: "huge_image_downloader")
downloader.downloadTimeout = 150.0
let cache = ImageCache(name: "longer_cache")
cache.maxDiskCacheSize = 60 * 60 * 24 * 30

imageView.kf.setImage(with: url, options: [.downloader(downloader), .targetCache(cache)])

取消下载或者重新下载

// In table view data source
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//...
cell.imageView.kf.setImage(with: url)
//...
}

// In table view delegate
func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
//...
cell.imageView.kf.cancelDownloadTask()
}

发送前修改请求

let modifier = AnyModifier { request in
var r = request
r.setValue("", forHTTPHeaderField: "Access-Token")
return r
}       
imageView.kf.setImage(with: url, placeholder: nil, options: [.requestModifier(modifier)])

身份验证NSURLCredential

// In ViewController
ImageDownloader.default.authenticationChallengeResponder = self

extension ViewController: AuthenticationChallengeResponsable {
func downloader(_ downloader: ImageDownloader,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
{
// Provide your `AuthChallengeDisposition` and `URLCredential`
let disposition: URLSession.AuthChallengeDisposition = // ..
let credential: URLCredential? = //..
completionHandler(disposition, credential)
}
}

检查HTTP状态码确认是否有效

// In ViewController
ImageDownloader.default.delegate = self

extension ViewController: ImageDownloaderDelegate {
func isValidStatusCode(_ code: Int, for downloader: ImageDownloader) -> Bool {
return code == 200 || code == 202
}
}

在下载器中使用自己的会话配置

let imageDownloader: ImageDownloader = //...

// A configuration without persistent storage for caches is 
// requsted for downloader working correctly. (Based on `URLSessionConfiguration.ephemeral`)
imageDownloader.sessionConfiguration = //...

处理器

ImageProcessor更像是图像的变形。它将一些数据转换为图像或图像。你可以提供一个处理器ImageDownloader。下载器会将其应用于下载的数据/图像,然后在需要时将处理后的图像发送到图像视图或缓存。

使用默认处理器

// Just without anything
imageView.kf.setImage(with: url)
// It equals to
imageView.kf.setImage(with: url, options: [.processor(DefaultImageProcessor.default)])

默认处理器将下载的数据转换为相应的图像对象,PNG,JPEG和GIF都支持。

内置处理器

// Round corner
let processor = RoundCornerImageProcessor(cornerRadius: 20)

// Resizing
let processor = ResizingImageProcessor(referenceSize: CGSize(width: 100, height: 100))

// Cropping
let processor = CroppingImageProcessor(size: CGSize(width: 100, height: 100), anchor: CGPoint(x: 0.5, y: 0.5))

// Blur with a radius
let processor = BlurImageProcessor(blurRadius: 5.0)

// Overlay with a color & fraction
let processor = OverlayImageProcessor(overlay: .red, fraction: 0.7)

// Tint with a color
let processor = TintImageProcessor(tint: .blue)

// Adjust color
let processor = ColorControlsProcessor(brightness: 1.0, contrast: 0.7, saturation: 1.1, inputEV: 0.7)

// Black & White
let processor = BlackWhiteProcessor()

// Blend (iOS)
let processor = BlendImageProcessor(blendMode: .darken, alpha: 1.0, backgroundColor: .lightGray)

// Compositing
let processor = CompositingImageProcessor(compositingOperation: .darken, alpha: 1.0, backgroundColor: .lightGray)

imageView.kf.setImage(with: url, options: [.processor(processor)])

连接处理器

// Blur and then make round corner
let processor = BlurImageProcessor(blurRadius: 5.0) >> RoundCornerImageProcessor(cornerRadius: 20)
imageView.kf.setImage(with: url, options: [.processor(processor)])

// `>>` equals the `append(another:)` method of `ImageProcessor`.
// Above equals to:
let processor = BlurImageProcessor(blurRadius: 5.0).append(RoundCornerImageProcessor(cornerRadius: 20))

创建并使用自己的处理器

struct WebpProcessor: ImageProcessor {
// `identifier` should be the same for processors with same properties/functionality
// It will be used when storing and retrieving the image to/from cache.
let identifier = "com.yourdomain.webpprocessor"

// Convert input data/image to target image and return it.
func process(item: ImageProcessItem, options: KingfisherOptionsInfo) -> Image? {
switch item {
case .image(let image):
print("already an image")
return image
case .data(let data):
return WebpFramework.createImage(from: webpData)
}
}
}

// Then pass it to the `setImage` methods:
let processor = WebpProcessor()
let url = URL(string: "https://yourdomain.com/example.webp")
imageView.kf.setImage(with: url, options: [.processor(processor)])

创建过滤

struct MyCIFilter: CIImageProcessor {

let identifier = "com.yourdomain.myCIFilter"

let filter = Filter { input in
guard let filter = CIFilter(name: "xxx") else { return nil }
filter.setValue(input, forKey: kCIInputBackgroundImageKey)
return filter.outputImage
}
}

使用处理器缓存

let processor = WebpProcessor()
let url = URL(string: "https://yourdomain.com/example.webp")
imageView.kf.setImage(with: url, options: [.processor(processor)])

// Later
ImageCache.default.isImageCached(
forKey: url.cacheKey, 
processorIdentifier: processor.identifier)

缓存原始图像用于多个处理器处理

let p = MyProcessor()
imageView.kf.setImage(with: url, options: [.processor(p), .cacheOriginalImage])

使用序列化程序

// Just without anything
imageView.kf.setImage(with: url)
// It equals to
imageView.kf.setImage(with: url, options: [.cacheSerializer(DefaultCacheSerializer.default)])

指定缓存格式

let roundCorner = RoundCornerImageProcessor(cornerRadius: 20)
imageView.kf.setImage(with: url, 
options: [.processor(roundCorner), 
.cacheSerializer(FormatIndicatedCacheSerializer.png)]
)

创建自定义的序列化程序

struct WebpCacheSerializer: CacheSerializer {
func data(with image: Image, original: Data?) -> Data? {
return WebpFramework.webpData(of: image)
}

func image(with data: Data, options: KingfisherOptionsInfo?) -> Image? {
return WebpFramework.createImage(from: webpData)
}
}

// Then pass it to the `setImage` methods:
let serializer = WebpCacheSerializer()
let url = URL(string: "https://yourdomain.com/example.webp")
imageView.kf.setImage(with: url, options: [.cacheSerializer(serializer)])

预取

可以预先取出一些图像将其缓存,然后显示在屏幕上。

let urls = ["http://example.com/image1.jpg", "http://example.com/image2.jpg"]
.map { URL(string: $0)! }
let prefetcher = ImagePrefetcher(urls: urls) {
skippedResources, failedResources, completedResources in
print("These resources are prefetched: \(completedResources)")
}
prefetcher.start()

// Later when you need to display these images:
imageView.kf.setImage(with: urls[0])
anotherImageView.kf.setImage(with: urls[1])

Prefetcher与UICollectionView或UITableView一起使用

override func viewDidLoad() {
super.viewDidLoad()
collectionView?.prefetchDataSource = self
}

extension ViewController: UICollectionViewDataSourcePrefetching {
func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) {
let urls = indexPaths.flatMap { URL(string: $0.urlString) }
ImagePrefetcher(urls: urls).start()
}
}

动画GIF

let imageView: UIImageView = ...
imageView.kf.setImage(with: URL(string: "your_animated_gif_image_url")!)

如果在处理大型GIF时遇到内存问题,请尝试使用AnimatedImageView而不是常规图像视图来显示GIF。它只会解码您的GIF图像的几个帧,以获得更小的内存占用(但CPU负载很高)。

let imageView = AnimatedImageView()
imageView.kf.setImage(with: URL(string: "your_large_animated_gif_image_url")!)

只加载来自GIF的第一帧

imageView.kf.setImage(with: URL(string: "your_animated_gif_image_url")!, 
options: [.onlyLoadFirstFrame])

图片扩展

可以使用处理器/过滤器来单独处理图像。

extension Image {
public func kf.image(withRoundRadius radius: CGFloat, fit size: CGSize, scale: CGFloat) -> Image { }
public func kf.resize(to size: CGSize) -> Image { }
public func kf.blurred(withRadius radius: CGFloat) -> Image { }
public func kf.overlaying(with color: Color, fraction: CGFloat) -> Image { }
public func kf.tinted(with color: Color) -> Image { }
public func kf.adjusted(brightness: CGFloat, contrast: CGFloat, saturation: CGFloat, inputEV: CGFloat) -> Image { }
public func kf.apply(_ filter: Filter) -> Image { }
}

你可能感兴趣的:(Kingfisher使用备忘录)