版本记录
| 版本号 | 时间 |
|---|---|
| V1.0 | 2018.12.27 星期四 |
前言
OC对有一个很棒的网络图片加载控件SDWebImage,那么Swift中呢,如果要加载远程网络图片呢?这里接下来几篇就给大家介绍一个Swift中用于加载网络图片的框架 —— Nuke。
概览
首先我们看一下作者
它是强大的图像加载和缓存系统。 它使得将图像加载到视图中的任务非常简单,同时还支持更高要求的应用程序的高级功能。
快速LRU内存缓存,本机HTTP磁盘缓存和自定义主动LRU磁盘缓存
逐步图像加载(渐进式JPEG和WebP)
可恢复的下载,请求优先级,重复数据删除,速率限制等
使用Preheat自动prefetching(在iOS 10中已弃用)
Getting Started
详细Image Pipeline描述
整个部分致力于Performance
Contributing和路线图
更多信息可在Documentation目录和完整的API Reference中找到。 当您准备好安装Nuke时,您可以遵循Installation Guide - 支持所有主要的包管理器。
Quick Start
1. Load Image into Image View
您可以使用一行代码将图像加载到图像视图中。
Nuke.loadImage(with: url, into: imageView)
Nuke将自动加载图像数据,在后台解压缩,将图像存储在内存缓存中并显示它。
要学习
ImagePipeline,see the dedicated section
当您为视图请求新图像时,先前未完成的请求将被取消,图像将设置为nil。 视图dealloc时,请求也会自动取消。
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
...
Nuke.loadImage(with: url, into: cell.imageView)
...
}2. Placeholders, Transitions and More
使用options参数(ImageLoadingOptions)自定义图像的加载和显示方式。 您可以提供占位符,选择其中一个内置过渡(transition)或提供自定义过渡。 使用过渡时,请注意UIKit可能会保留对图像的引用,以防止因为长动画或一次加载多个过渡而被移除。
Nuke.loadImage( with: url, options: ImageLoadingOptions( placeholder: UIImage(named: "placeholder"), transition: .fadeIn(duration: 0.33) ), into: imageView)
有一个很常用的场景:当占位符(或失败的图像)需要以与用于加载的图像不同的content mode显示时。
let options = ImageLoadingOptions( placeholder: UIImage(named: "placeholder"), failureImage: UIImage(named: "failure_image"), contentModes: .init( success: .scaleAspectFill, failure: .center, placeholder: .center ) ) Nuke.loadImage(with: url, options: options, into: imageView)
要使应用程序中的所有图像视图共享相同的行为,请修改ImageLoadingOptions.shared。
如果
ImageLoadingOptions缺少您需要的功能,请直接使用ImagePipeline。 如果您认为每个人都可以从此功能中受益,PRs是不错的选择。
3. Image Requests
每次请求都是ImageRequest表示的,一次请求可以有URL或者URLRequest创建。
var request = ImageRequest(url: url)// var request = ImageRequest(urlRequest: URLRequest(url: url))// Change memory cache policy:request.memoryCacheOptions.isWriteAllowed = false// Update the request priority:request.priority = .high Nuke.loadImage(with: request, into: imageView)
4. Process an Image
使用特殊的ImageRequest初始化器改变图片的尺寸。
// Target size is in pixels.ImageRequest(url: url, targetSize: CGSize(width: 640, height: 320), contentMode: .aspectFill)
使用processed(key:closure:)方法执行自定义转换。 以下是使用Toucan创建circular avatar的方法。
ImageRequest(url: url).process(key: "circularAvatar") {
Toucan(image: $0).maskWithEllipse().image
}所有这些API都建立在ImageProcessing协议之上,您也可以使用它来实现自定义处理器。 请记住,ImageProcessing还需要遵守Equatable,这有助于Nuke识别内存缓存中的图像。
Nuke中使用Core Image,请参考Core Image Integration Guide
Advanced Usage
1. Image Pipeline
直接使用ImagePipeline加载图像,不用view
let task = ImagePipeline.shared.loadImage(
with: url,
progress: { _, completed, total in
print("progress updated")
},
completion: { response, error in
print("task completed")
}
)任务可用于监视下载进度,取消请求以及动态更新下载优先级。
task.cancel()task.setPriority(.high)
有关ImagePipeline的更多信息,请see the dedicated section
2. Configuring Image Pipeline
除了使用共享的ImagePipeline实例外,您还可以创建自己的实例。
let pipeline = ImagePipeline {
$0.dataLoader = ...
$0.dataLoadingQueue = ...
$0.imageCache = ...
...
}// When you're done you can make the pipeline a shared one:ImagePipeline.shared = pipeline3. Memory Cache
默认Nuke的ImagePipeline有两个缓存层。
首先,有一个缓存专门用来存储用来准备显示的处理过的图像。 您可以直接访问此缓存:
// Configure cacheImageCache.shared.costLimit = 1024 * 1024 * 100 // 100 MBImageCache.shared.countLimit = 100ImageCache.shared.ttl = 120 // Invalidate image after 120 sec// Read and write imageslet request = ImageRequest(url: url) ImageCache.shared[request] = imagelet image = ImageCache.shared[request]// Clear cacheImageCache.shared.removeAll()
4. HTTP Disk Cache
为了存储未处理的图像数据,Nuke使用URLCache实例:
// Configure cacheDataLoader.sharedUrlCache.diskCapacity = 100DataLoader.sharedUrlCache.memoryCapacity = 0// Read and write responseslet request = ImageRequest(url: url)let _ = DataLoader.sharedUrlCache.cachedResponse(for: request.urlRequest) DataLoader.sharedUrlCache.removeCachedResponse(for: request.urlRequest)// Clear cacheDataLoader.sharedUrlCache.removeAllCachedResponses()
5. Aggressive Disk Cache
自定义LRU磁盘缓存可用于快速可靠的主动数据缓存(忽略HTTP cache control)。 您可以使用管道配置启用它。
$0.dataCache = try! DataCache(name: "com.myapp.datacache")// On Swift 4.1 and lower you'll also need to provide a `FilenameGenerator`.
如果启用了主动磁盘缓存,请确保还禁用本机URL缓存(请参阅DataLoader),否则最终可能会存储两次相同的映像数据。
DataCache类型实现公共DataCaching协议,可用于实现自定义数据缓存。
6. Prefetching Images
预先Prefethcing图像可以减少用户的等待时间。 Nuke提供了一个ImagePreheater来做到这一点:
let preheater = ImagePreheater() preheater.startPreheating(with: urls)// Cancels all of the preheating tasks created for the given requests.preheater.stopPreheating(with: urls)
需要权衡,prefetching会占用用户的数据,并对CPU和内存造成额外压力。 要减少CPU和内存使用量,您可以选择仅将磁盘缓存作为prefetching目标:
// The preheater with `.diskCache` destination will skip image data decoding// entirely to reduce CPU and memory usage. It will still load the image data// and store it in disk caches to be used later.let preheater = ImagePreheater(destination: .diskCache)
为确保prefetching请求不会干扰正常请求,最好降低其优先级。
您可以将Nuke与Preheat库结合使用,该库可自动preheating UICollectionView和UITableView中的内容。 在iOS 10.0上,您可能希望使用iOS提供的新prefetching APIs。
7. Progressive Decoding
要使用渐进式图像加载,您需要启用渐进式解码的管道。
let pipeline = ImagePipeline { $0.isProgressiveDecodingEnabled = true}就是这样,你可以开始观察管道产生的图像。 进度处理程序也可用作渐进式图像处理程序。
let imageView = UIImageView()let task = ImagePipeline.shared.loadImage( with: url, progress: { response, _, _ in
imageView.image = response?.image
}, completion: { response, _ in
imageView.image = response?.image
}
)请参阅
"Progressive Decoding"演示,了解渐进式JPEG在实践中的应用。
8. Animated Images
Nuke使用animatedImageData属性扩展UIImage。 如果通过将ImagePipeline.Configuration.isAnimatedImageDataEnabled设置为true来启用它,则管道将开始将原始图像数据附加到动画图像(内置解码器现在仅支持GIF)。
在计算缓存项目的成本时,
ImageCache会将animatedImageData考虑在内。ImagePipeline不会将处理器应用于带有动画数据的图像。
没有内置的方法来渲染这些图像,但有两种可用的集成:FLAnimatedImage和Gifu,它们既快速又高效。
GIF不是传输和显示动画图像的最有效格式。 目前的最佳做法是use short videos instead of GIFs(例如MP4,WebM)。 演示项目中有一个PoC,它使用Nuke加载,缓存和显示MP4视频。
9. WebP
WebP支持由Ryo Kosuge构建的Nuke WebP Plugin插件提供。 请按照repo中的说明进行安装。
10. RxNuke
RxNuke为Nuke添加了RxSwift扩展,并支持许多常见用例:
And more...
以下是将go flow log加载到高分辨率是多么容易的示例:
let pipeline = ImagePipeline.shared
Observable.concat(pipeline.loadImage(with: lowResUrl).orEmpty,
pipeline.loadImage(with: highResUtl).orEmpty)
.subscribe(onNext: { imageView.image = $0 })
.disposed(by: disposeBag)Image Pipeline
Nuke的图像管道由大约五个阶段组成,可以使用以下协议进行自定义:
作者:刀客传奇
链接:https://www.jianshu.com/p/d2a34eb67d8c