AlamofireImage

Build Status CocoaPods Compatible Carthage Compatible Platform Twitter Gitter

AlamofireImage 是 Alamofire 的一个图像组件库。

特性

要求

迁移指南

依赖

沟通

安装

CocoaPods

CocoaPods 是 Cocoa 项目的依赖管理器。 有关使用和安装说明,请访问他们的网站。 要使用 CocoaPods 将 AlamofireImage 集成到您的 Xcode 项目中,请在您的 Podfile 中指定它

pod 'AlamofireImage', '~> 4.3'

Carthage

Carthage 是一个去中心化的依赖管理器,可以构建您的依赖项并为您提供二进制框架。 要使用 Carthage 将 AlamofireImage 集成到您的 Xcode 项目中,请在您的 Cartfile 中指定它

github "Alamofire/AlamofireImage" ~> 4.3

Swift Package Manager

Swift Package Manager 是一种用于自动化 Swift 代码分发的工具,并已集成到 swift 编译器中。 它还处于早期开发阶段,但 AlamofireImage 确实支持在支持的平台上使用它。

设置好 Swift 包后,将 AlamofireImage 添加为依赖项就像将其添加到 Package.swiftdependencies 值一样容易。

dependencies: [
    .package(url: "https://github.com/Alamofire/AlamofireImage.git", .upToNextMajor(from: "4.3.0"))
]

手动

如果您不想使用上述任何一个依赖管理器,您可以手动将 AlamofireImage 集成到您的项目中。

嵌入式框架

$ git init
$ git submodule add https://github.com/Alamofire/AlamofireImage.git

用法

图像响应序列化器

import Alamofire
import AlamofireImage

AF.request("https://httpbin.org/image/png").responseImage { response in
  debugPrint(response)

  print(response.request)
  print(response.response)
  debugPrint(response.result)

  if case .success(let image) = response.result {
    print("image downloaded: \(image)")
  }
}

AlamofireImage 响应图像序列化器支持各种图像类型,包括

如果您尝试下载的图像是不在列表中的无效 MIME 类型,则可以使用 DataRequest 类型上的 addAcceptableImageContentTypes 扩展来添加自定义可接受的内容类型。

UIImage 扩展

有几个 UIImage 扩展旨在使常见的图像操作尽可能简单。

解压缩

let url = Bundle.main.url(forResource: "unicorn", withExtension: "png")!
let data = try! Data(contentsOf: url)
let image = UIImage(data: data, scale: UIScreen.main.scale)!

image.af.inflate()

在后台队列中解压缩压缩图像格式(例如 PNG 或 JPEG)可以显着提高主线程上的绘图性能。

缩放

let image = UIImage(named: "unicorn")!
let size = CGSize(width: 100.0, height: 100.0)

// Scale image to size disregarding aspect ratio
let scaledImage = image.af.imageScaled(to: size)

// Scale image to fit within specified size while maintaining aspect ratio
let aspectScaledToFitImage = image.af.imageAspectScaled(toFit: size)

// Scale image to fill specified size while maintaining aspect ratio
let aspectScaledToFillImage = image.af.imageAspectScaled(toFill: size)

圆角

let image = UIImage(named: "unicorn")!
let radius: CGFloat = 20.0

let roundedImage = image.af.imageRounded(withCornerRadius: radius)
let circularImage = image.af.imageRoundedIntoCircle()

Core Image 滤镜

let image = UIImage(named: "unicorn")!

let sepiaImage = image.af.imageFiltered(withCoreImageFilter: "CISepiaTone")

let blurredImage = image.af.imageFiltered(
    withCoreImageFilter: "CIGaussianBlur",
    parameters: ["inputRadius": 25]
)

图像滤镜

ImageFilter 协议旨在使应用滤镜操作并在图像下载完成后缓存结果变得容易。 它定义了两个属性来促进此功能。

public protocol ImageFilter {
    var filter: Image -> Image { get }
    var identifier: String { get }
}

filter 闭包包含用于创建指定图像的修改版本的操作。 identifier 属性是一个字符串,用于唯一标识滤镜操作。 在将图像的过滤版本添加到缓存时,这很有用。 AlamofireImage 中的所有标识符属性都使用协议扩展来实现。

单通道

单通道图像滤镜仅对指定图像执行单个操作。

let image = UIImage(named: "unicorn")!
let imageFilter = RoundedCornersFilter(radius: 10.0)

let roundedImage = imageFilter.filter(image)

当前的单通道图像滤镜列表包括

每个图像滤镜都建立在 UIImage 扩展之上。

多通道

多通道图像滤镜对指定的图像执行多个操作。

let image = UIImage(named: "avatar")!
let size = CGSize(width: 100.0, height: 100.0)
let imageFilter = AspectScaledToFillSizeCircleFilter(size: size)

let avatarImage = imageFilter.filter(image)

当前的多通道图像滤镜列表包括

图像缓存

当涉及到网络图像时,图像缓存可能会变得很复杂。 URLCache 非常强大,并且在推理各种缓存策略和 Cache-Control 标头方面做得很好。 但是,它没有配备处理缓存这些图像的多个修改版本。

例如,假设您需要下载一个图像专辑。 您的应用需要在不同时间显示缩略图版本和完整大小版本。 由于性能问题,您希望在将缩略图呈现在屏幕上之前将其缩小到合理的大小。 您还需要在显示完整尺寸图像时将全局 CoreImage 滤镜应用于完整尺寸图像。 虽然 URLCache 可以轻松处理存储原始下载的图像,但它无法存储这些不同的变体。 您真正需要的是另一个缓存层来处理这些不同的变体。

let imageCache = AutoPurgingImageCache(
    memoryCapacity: 100_000_000,
    preferredMemoryUsageAfterPurge: 60_000_000
)

AlamofireImage 中的 AutoPurgingImageCache 填补了该附加缓存层的角色。 它是一个内存中的图像缓存,用于存储图像,最大存储量为给定的内存容量。 当达到内存容量时,图像缓存按上次访问日期排序,然后连续清除最旧的图像,直到满足清除后首选内存使用量为止。 每次通过缓存访问图像时,都会更新图像的内部访问日期。

添加 / 删除 / 获取图像

ImageCache 协议 API 交互非常简单。

let imageCache = AutoPurgingImageCache()
let avatarImage = UIImage(data: data)!

// Add
imageCache.add(avatarImage, withIdentifier: "avatar")

// Fetch
let cachedAvatar = imageCache.image(withIdentifier: "avatar")

// Remove
imageCache.removeImage(withIdentifier: "avatar")

URL 请求

ImageRequestCache 协议通过添加对 URLRequest 缓存的支持来扩展 ImageCache 协议。 这允许 URLRequest 和附加标识符生成缓存中图像的唯一标识符。

let imageCache = AutoPurgingImageCache()

let urlRequest = URLRequest(url: URL(string: "https://httpbin.org/image/png")!)
let avatarImage = UIImage(named: "avatar")!.af.imageRoundedIntoCircle()

// Add
imageCache.add(avatarImage, for: urlRequest, withIdentifier: "circle")

// Fetch
let cachedAvatarImage = imageCache.image(for: urlRequest, withIdentifier: "circle")

// Remove
imageCache.removeImage(for: urlRequest, withIdentifier: "circle")

自动清除

每次从缓存中获取图像时,缓存都会在内部更新该图像的上次访问日期。

let avatar = imageCache.image(withIdentifier: "avatar")
let circularAvatar = imageCache.image(for: urlRequest, withIdentifier: "circle")

通过更新每个图像的上次访问日期,图像缓存可以做出更明智的决定,即在达到内存容量时清除哪些图像。 AutoPurgingImageCache 会自动从缓存中删除图像,顺序从最旧的上次访问日期到最新的上次访问日期,直到内存容量降至 preferredMemoryCapacityAfterPurge 以下。

在初始化图像缓存时,设置 memoryCapacitypreferredMemoryCapacityAfterPurge 的合理默认值非常重要。 默认情况下,memoryCapacity 等于 100 MB,preferredMemoryCapacityAfterPurge 等于 60 MB。

内存警告

AutoPurgingImageCache 还会侦听来自您应用程序的内存警告,并且如果在观察到内存警告时会从缓存中清除所有图像。

图像下载器

ImageDownloader 类负责在优先级队列上并行下载图像。 它使用内部 Alamofire SessionManager 实例来处理所有下载和响应图像序列化。 默认情况下,ImageDownloader 的初始化使用带有最常见参数值的默认 URLSessionConfiguration

let imageDownloader = ImageDownloader(
    configuration: ImageDownloader.defaultURLSessionConfiguration(),
    downloadPrioritization: .fifo,
    maximumActiveDownloads: 4,
    imageCache: AutoPurgingImageCache()
)

如果您需要自定义 URLSessionConfiguration 类型或参数,只需提供您自己的类型,而不是使用默认类型。

下载图像

let downloader = ImageDownloader()
let urlRequest = URLRequest(url: URL(string: "https://httpbin.org/image/jpeg")!)

downloader.download(urlRequest) { response in
    print(response.request)
    print(response.response)
    debugPrint(response.result)

    if case .success(let image) = response.result {
        print(image)
    }
}

请确保保持对 ImageDownloader 实例的强引用,否则 completion 闭包将不会被调用,因为 downloader 引用将在可以调用 completion 闭包之前超出范围。

应用 ImageFilter

let downloader = ImageDownloader()
let urlRequest = URLRequest(url: URL(string: "https://httpbin.org/image/jpeg")!)
let filter = AspectScaledToFillSizeCircleFilter(size: CGSize(width: 100.0, height: 100.0))

downloader.download(urlRequest, filter: filter) { response in
    print(response.request)
    print(response.response)
    debugPrint(response.result)

    if case .success(let image) = response.result {
        print(image)
    }
}

身份验证

如果您的图像位于 HTTP 基本身份验证后面,您可以将 user:password:credential 附加到 ImageDownloader 实例。 凭据将应用于所有未来的下载请求。

let downloader = ImageDownloader()
downloader.addAuthentication(user: "username", password: "password")

下载优先级

ImageDownloader 维护一个挂起的下载请求的内部队列。 根据您的情况,您可能希望将传入的下载插入到队列的前面或后面。 DownloadPrioritization 枚举允许您指定您更喜欢哪种行为。

public enum DownloadPrioritization {
    case fifo, lifo
}

默认情况下,ImageDownloader 使用 .fifo 队列初始化。

图像缓存

ImageDownloader 结合使用了 URLCacheAutoPurgingImageCache,创建了一个非常强大、高性能的图像缓存系统。

URLCache

URLCache 用于缓存从服务器下载的所有原始图像内容。 默认情况下,它被初始化为具有 20 MB 的内存容量和 150 MB 的磁盘容量。 这允许在任何给定时间在磁盘上存储最多 150 MB 的原始图像数据。 虽然这些默认值已经过仔细设置,但非常重要的是要考虑应用程序的需求和性能要求,以及这些值是否适合您。

如果您希望禁用此缓存层,请创建一个自定义 URLSessionConfiguration,并将 urlCache 属性设置为 nil,并在初始化 ImageDownloader 时使用该配置。

图像缓存

ImageCache 用于缓存从服务器下载后所有可能经过滤的图像内容。 这允许缓存同一图像的多个变体,而不必每次需要时都将图像滤镜重新应用于原始图像。 默认情况下,AutoPurgingImageCache 被初始化为具有 100 MB 的内存容量和 60 MB 的首选清除后内存使用限制。 这允许在给定时间在内存中存储最多 100 MB 的最近访问过的过滤图像内容。

设置理想的容量限制

确定 URLCacheAutoPurgingImageCache 的理想内存和磁盘容量限制需要一些预见性。 您必须仔细考虑应用程序的需求,并相应地调整限制。 默认情况下,缓存组合提供以下存储容量

如果您不使用图像滤镜,建议将 URLCache 的内存容量设置为零。 否则,您会将原始图像数据存储在 URLCache 的内存存储以及 AlamofireImage 的内存存储中。

重复下载

有时,应用程序逻辑最终可能会在初始下载请求完成之前尝试多次下载图像。 最常见的是,这会导致图像被多次下载。 AlamofireImage 通过合并重复下载来优雅地处理这种情况。 图像只会下载一次,但会调用两个完成处理程序。

图像滤镜重用

除了合并重复下载外,AlamofireImage 还可以合并重复的图像滤镜。 如果两个具有相同标识符的图像滤镜附加到同一个下载,则图像滤镜仅执行一次,并且使用相同的生成图像调用两个完成处理程序。 对于计算量大的滤镜(例如利用 CoreImage 的滤镜),这可以节省大量时间和资源。

请求回执

有时,出于各种原因,需要取消图像下载。 AlamofireImage 可以通过利用 RequestReceipt 类型以及 cancelRequestForRequestReceipt 方法,在 ImageDownloader 中智能地处理取消逻辑。 每个下载请求都会提供一个 RequestReceipt,稍后可用于取消该请求。

通过使用 RequestReceipt,通过 ImageDownloader 取消请求,AlamofireImage 能够确定如何最好地处理取消。 取消的下载将始终收到取消错误,而重复的下载则可以完成。 如果下载已在进行中,则允许完成,即使将使用取消错误调用完成处理程序。 这大大提高了显示大量图像的表和集合视图的性能。

不建议直接在 RequestReceipt 中调用 request 上的 cancel。 这样做可能会导致诸如重复下载永远无法完成的问题。

UIImageView 扩展

UIImage 扩展图像滤镜图像缓存图像下载器 的设计都具有灵活性和独立性,但也为 UIImageView 扩展提供了基础。 由于这些类、协议和扩展的强大支持,UIImageView API 简洁、易于使用并包含大量功能。

使用 URL 设置图像

使用 URL 设置图像将异步下载图像,并在请求完成后设置图像。

let imageView = UIImageView(frame: frame)
let url = URL(string: "https://httpbin.org/image/png")!

imageView.af.setImage(withURL: url)

如果图像已在本地缓存,则会立即设置图像。

占位符图像

通过指定占位符图像,图像视图使用占位符图像,直到下载远程图像。

let imageView = UIImageView(frame: frame)
let url = URL(string: "https://httpbin.org/image/png")!
let placeholderImage = UIImage(named: "placeholder")!

imageView.af.setImage(withURL: url, placeholderImage: placeholderImage)

如果远程图像已在本地缓存,则永远不会设置占位符图像。

图像滤镜

如果指定了图像滤镜,则会在下载远程图像后异步应用。 滤镜执行完成后,结果图像将设置在图像视图上。

let imageView = UIImageView(frame: frame)

let url = URL(string: "https://httpbin.org/image/png")!
let placeholderImage = UIImage(named: "placeholder")!

let filter = AspectScaledToFillSizeWithRoundedCornersFilter(
    size: imageView.frame.size,
    radius: 20.0
)

imageView.af.setImage(
    withURL: url,
    placeholderImage: placeholderImage,
    filter: filter
)

如果应用滤镜的远程图像已在本地缓存,则会立即设置图像。

图像过渡

默认情况下,在图像视图上设置图像时,没有图像过渡动画。 如果您希望添加交叉溶解或从底部翻转动画,请指定具有首选持续时间的 ImageTransition

let imageView = UIImageView(frame: frame)

let url = URL(string: "https://httpbin.org/image/png")!
let placeholderImage = UIImage(named: "placeholder")!

let filter = AspectScaledToFillSizeWithRoundedCornersFilter(
    size: imageView.frame.size,
    radius: 20.0
)

imageView.af.setImage(
    withURL: url,
    placeholderImage: placeholderImage,
    filter: filter,
    imageTransition: .crossDissolve(0.2)
)

如果远程图像已在本地缓存,则会忽略图像过渡。

图像下载器

UIImageView 扩展由默认的 ImageDownloader 实例提供支持。 要自定义缓存容量、下载优先级、请求缓存策略、超时持续时间等,请参阅 图像下载器 文档。

身份验证

如果图像需要来自 UIImageView 扩展的身份验证凭据,则可以按如下方式提供

ImageDownloader.default.addAuthentication(user: "user", password: "password")

鸣谢

Alamofire 由 Alamofire Software Foundation 拥有和维护。 您可以在 Twitter 上关注他们 @AlamofireSF,以获取项目更新和发布。

安全披露

如果您认为您已发现 AlamofireImage 的安全漏洞,您应尽快通过电子邮件将其报告给 security@alamofire.org。 请不要将其发布到公共问题跟踪器。

捐款

ASF 正在筹集资金以正式注册为联邦非营利组织。 注册将使我们的成员获得一些法律保护,并使我们能够免税地使用捐款。 向 ASF 捐款将使我们能够

社区对 ASF 库的采用非常惊人。 我们对您对项目的热情感到非常荣幸,并希望继续尽一切努力推动发展。 在您的持续支持下,ASF 将能够扩大其影响范围,并为核心成员提供更好的法律保障。 如果您在工作中使用我们的任何库,请查看您的雇主是否有兴趣捐款。 您今天可以捐赠的任何金额都将不胜感激,以帮助我们实现我们的目标。

paypal

许可证

AlamofireImage 在 MIT 许可证下发布。 有关详细信息,请参见 LICENSE