AlamofireImage
AlamofireImage 是 Alamofire 的图像组件库。
特性
- 图像响应序列化器
- UIImagextensions 增量/缩放/圆角/ CoreImage
- 单次和多次通过图像过滤器
- 自动清除内存中图像缓存
- 优先队列顺序图像下载
- 使用 URLCredential 进行身份验证
- 使用占位符的 UIImageView 异步远程下载
- UIImageView 过滤器和过渡效果
- 全面测试覆盖
- 完整的文档
要求
- iOS 10.0+ / macOS 10.12+ / tvOS 10.0+ / watchOS 3.0+
- Xcode 11+
- Swift 5.1+
迁移指南
依赖项
通信
- 如果您需要
找到或理解一个API,请查看
我们的文档。 - 如果您需要帮助
使用AlamofireImage功能,请使用
我们的swift.org论坛。 - 如果您想讨论
AlamofireImage的最佳实践,请使用
我们的swift.org论坛。 - 如果您想讨论
功能请求,请使用
我们的swift.org论坛。 - 如果您发现了
错误,请创建一个问题并遵循指南。越详细越好! - 如果您想要
贡献,请提交一个拉取请求。
安装
CocoaPods
CocoaPods是Cocoa项目的依赖项管理器。有关用法和安装说明,请访问他们的网站。要将AlamofireImage集成到使用CocoaPods的Xcode项目中,请在其Podfile
中指定它。
pod 'AlamofireImage', '~> 4.1'
Carthage
Carthage是一款去中心化的依赖项管理器,它构建您的依赖项并向您提供二进制框架。要将AlamofireImage集成到使用Carthage的Xcode项目中,请在其Cartfile
中指定它。
github "Alamofire/AlamofireImage" ~> 4.1
Swift 包管理器
Swift 包管理器是用于自动分发 Swift 代码的工具,并集成在 swift
编译器中。它目前还处于早期开发阶段,但 AlamofireImage 支持在支持的平台上使用它。
一旦你设置了自己的 Swift 包,将 AlamofireImage 添加为依赖项就像将它添加到 Package.swift
中的 dependencies
值一样简单。
dependencies: [
.package(url: "https://github.com/Alamofire/AlamofireImage.git", .upToNextMajor(from: "4.1.0"))
]
手动安装
如果你不希望使用上述任一依赖管理器,你可以手动将 AlamofireImage 整合到项目中。
嵌入式框架
- 打开终端,使用
cd
命令进入您的顶级项目目录,如果您的项目未初始化为 git 仓库,请运行以下命令
$ git init
- 通过运行以下命令将 AlamofireImage 添加为 git 子模块
$ git submodule add https://github.com/Alamofire/AlamofireImage.git
-
打开新的
AlamofireImage
文件夹,并将AlamofireImage.xcodeproj
拖放到您的应用 Xcode 项目的导航器中。它应该出现在您的应用蓝色项目图标下面。它位于其他 Xcode 组之上或之下无关紧要。
-
在项目导航器中选中
AlamofireImage.xcodeproj
并确认部署目标与您的应用目标匹配。 -
接下来,在项目导航器(蓝色项目图标)中选中您的应用项目,进入目标配置窗口,并在侧边栏的 "Targets" 下选择应用目标。
-
在该窗口的顶部标签栏中,打开 "General" 选项卡。
-
在 "Embedded Binaries" 部分的
+
按钮上单击。 -
您将看到两个不同的
AlamofireImage.xcodeproj
文件夹,每个文件夹中都有一个嵌套在Products
文件夹中的两个不同版本的AlamofireImage.framework
。您可以选择哪一个
Products
文件夹无关紧要,但您必须选择顶部或底部的AlamofireImage.framework
。 -
对于 iOS 选择顶部的
AlamofireImage.framework
,对于 OS X 选择底部的。您可以通过检查项目的构建日志来验证您选择了哪一个。AlamofireImage 的构建目标将列示为
AlamofireImage iOS
、AlamofireImage macOS
、AlamofireImage tvOS
或AlamofireImage watchOS
。 -
这样就可以了!
AlamofireImage.framework
会被自动添加为目标依赖项,链接框架和嵌入框架,在复制文件构建阶段完成,这就是在模拟器和设备上构建所需要的一切。
用法
图像响应序列化器
import Alamofire
import AlamofireImage
Alamofire.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响应图像序列化器支持广泛的图像格式,包括
image/png
image/jpeg
image/tiff
image/gif
image/ico
image/x-icon
image/bmp
image/x-bmp
image/x-xbitmap
image/x-ms-bmp
image/x-win-bitmap
application/octet-stream
(为支持iOS 13添加)
如果您尝试下载的图像是列表中不存在的无效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()
核心图像滤镜
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)
当前单次通过图像滤镜列表包括
ScaledToSizeFilter
- 将图像缩放到指定大小。AspectScaledToFitSizeFilter
- 从中心缩放图像,同时保持纵横比以适应指定大小。AspectScaledToFillSizeFilter
- 从中心缩放图像,同时保持纵横比以填充指定大小。超出指定大小的像素将被裁剪。RoundedCornersFilter
- 将图像的角落圆滑到指定的半径。CircleFilter
- 将图像的角落圆滑成一个圆。BlurFilter
- 使用具有指定模糊半径的CIGaussianBlur
滤镜模糊图像。
每个图像滤镜都是基于
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)
当前多级图像滤镜列表包括
ScaledToSizeWithRoundedCornersFilter
- 将图像缩放到指定大小,然后将角落圆滑到指定的半径。AspectScaledToFillSizeWithRoundedCornersFilter
- 从中心缩放图像,同时保持纵横比以适应指定大小,然后将角落圆滑到指定的半径。ScaledToSizeCircleFilter
- 将图像缩放到指定大小,然后将角落圆滑成一个圆。AspectScaledToFillSizeCircleFilter
- 以中心点缩放图像,同时保持宽高比,以适应指定的尺寸,然后将角落圆滑为圆形。
图像缓存
当网络图像涉及图像缓存时,会变得复杂。《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
。
在初始化图像缓存时,为
memoryCapacity
和preferredMemoryCapacityAfterPurge
设置合理的默认值非常重要。默认情况下,memoryCapacity
等于100 MB,而preferredMemoryCapacityAfterPurge
等于60 MB。
内存警告
自动清理图像缓存(AutoPurgingImageCache
)也会监听应用程序的内存警告,并在检测到内存警告时从缓存中清除所有图像。
图像下载器
负责在优先队列中并行下载图像的ImageDownloader
类。它使用内部的AlamofireSessionManager
实例来处理所有的下载和响应图像序列化。默认情况下,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
实例的强引用,否则由于downloader
引用在之前的completion
闭包可以调用之前就会超范围,因此不会调用completion
闭包。
应用图片过滤器
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基本身份验证后面,则可以将“用户:密码:
”或“凭据
”附加到ImageDownloader
实例上。这些凭据将被应用于所有未来的下载请求。
let downloader = ImageDownloader()
downloader.addAuthentication(user: "username", password: "password")
下载优先级
ImageDownloader
维护一个待处理下载请求的内部队列。根据您的具体情况,您可能希望将传入的下载插入队列的头部或尾部。《DownloadPrioritization》枚举允许您指定您更喜欢的行为。
public enum DownloadPrioritization {
case fifo, lifo
}
ImageDownloader
默认使用.fifo
队列进行初始化。
图像缓存
ImageDownloader
使用URLCache
和AutoPurgingImageCache
的组合创建一个非常健壮、高性能的图像缓存系统。
URLCache
URLCache
用于缓存从服务器下载的所有原始图像内容。默认情况下,它具有20 MB的内存容量和150 MB的磁盘容量。这允许在任何给定时间最多存储150 MB的原始图像数据。尽管这些默认值已经仔细设置,但非常重要的是要考虑您的应用程序的需求和性能要求以及这些值是否适合您。
如果您希望禁用此缓存层,创建一个自定义的
URLSessionConfiguration
,将urlCache
属性设置为nil
,并使用该配置初始化ImageDownloader
。
图片缓存
ImageCache
用于缓存从服务器下载后的所有可能被过滤的图片内容。这将允许同样图片的多个版本也被缓存,而不是每次需要时都必须对原始图片重新应用图像过滤器。默认情况下,使用了一个具有100 MB内存容量和60 MB清理过滤图像内容后首选内存使用量的AutoPurgingImageCache
。这允许最多100 MB最近的访问过的过滤图片内容在任意时刻存储在内存中。
设置理想容量限制
确定URLCache
和AutoPurgingImageCache
的内存和磁盘容量限制需要一定的前瞻性。您必须仔细考虑您应用程序的需求,并相应地调整限制。默认情况下,这些缓存组合提供以下存储容量:
- 150 MB的磁盘存储(仅原始图像)
- 20 MB的内存原始图像数据存储(仅原始图像)
- 100 MB的内存中过滤图像内容存储(使用过滤器时为过滤图像,否则为原始图像)
- 清理过滤图像内容后的60 MB首选内存容量
如果您不使用图像过滤器,建议将
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)以获取项目更新和发布信息。Alamofire Software Foundation
安全漏洞披露
如果您认为您发现了一个与AlamofireImage相关的安全漏洞,请尽快通过电子邮件报告给[email protected]。请不要将其发布到公共问题跟踪器。
捐款
ASF(Alamofire Software Foundation)正在寻求筹集资金,以正式注册为联邦非营利组织。注册将使我们会员获得一些法律保护,并使我们能够免税使用捐款。向ASF捐款将使我们能够:
- 支付我们每年的法律费用,以保持非营利组织的良好状态
- 支付我们的邮件服务器费用,帮助我们跟踪所有问题和安全问题
- 可能资助测试服务器,使我们更容易测试边缘情况
- 可能资助开发人员全职工作于我们的项目之一
ASF库在社区的采用率非常高。我们对您对项目的热情深感谦卑,并希望继续尽我们所能推进项目。在您的持续支持下,ASF将能够提高其影响力,并为核心成员提供更好的法律保障。如果您在工作中使用了我们的任何库,看看您的雇主是否愿意捐款。任何您今天可以捐赠以帮助我们达到目标的钱都将非常感激。
许可证
AlamofireImage是在MIT许可证下发布的。有关详细信息,请参阅LICENSE。