AlamofireImage 是 Alamofire 的一个图像组件库。
CocoaPods 是 Cocoa 项目的依赖管理器。 有关使用和安装说明,请访问他们的网站。 要使用 CocoaPods 将 AlamofireImage 集成到您的 Xcode 项目中,请在您的 Podfile
中指定它
pod 'AlamofireImage', '~> 4.3'
Carthage 是一个去中心化的依赖管理器,可以构建您的依赖项并为您提供二进制框架。 要使用 Carthage 将 AlamofireImage 集成到您的 Xcode 项目中,请在您的 Cartfile
中指定它
github "Alamofire/AlamofireImage" ~> 4.3
Swift Package Manager 是一种用于自动化 Swift 代码分发的工具,并已集成到 swift
编译器中。 它还处于早期开发阶段,但 AlamofireImage 确实支持在支持的平台上使用它。
设置好 Swift 包后,将 AlamofireImage 添加为依赖项就像将其添加到 Package.swift
的 dependencies
值一样容易。
dependencies: [
.package(url: "https://github.com/Alamofire/AlamofireImage.git", .upToNextMajor(from: "4.3.0"))
]
如果您不想使用上述任何一个依赖管理器,您可以手动将 AlamofireImage 集成到您的项目中。
cd
进入您的顶级项目目录,如果您的项目未初始化为 git 存储库,请运行以下命令“if”$ git init
$ git submodule add https://github.com/Alamofire/AlamofireImage.git
打开新的 AlamofireImage
文件夹,并将 AlamofireImage.xcodeproj
拖到应用程序的 Xcode 项目的 Project Navigator 中。
它应该出现在应用程序的蓝色项目图标下。 无论它位于所有其他 Xcode 组之上还是之下,都无关紧要。
在 Project Navigator 中选择 AlamofireImage.xcodeproj
,并验证部署目标是否与您的应用程序目标匹配。
接下来,在 Project Navigator 中选择您的应用程序项目(蓝色项目图标),以导航到目标配置窗口,并在侧栏中的“Targets”标题下选择应用程序目标。
在该窗口顶部的选项卡栏中,打开“General”面板。
单击“Embedded Binaries”部分下的 +
按钮。
您将看到两个不同的 AlamofireImage.xcodeproj
文件夹,每个文件夹都有两个不同版本的 AlamofireImage.framework
嵌套在 Products
文件夹中。
您选择哪个
Products
文件夹并不重要,但选择顶部还是底部的AlamofireImage.framework
确实很重要。
对于 iOS,选择顶部的 AlamofireImage.framework
,对于 OS X,选择底部的 AlamofireImage.framework
。
您可以通过检查项目的构建日志来验证您选择的哪个。
AlamofireImage
的构建目标将被列为AlamofireImage iOS
、AlamofireImage macOS
、AlamofireImage tvOS
或AlamofireImage watchOS
。
就这样!
AlamofireImage.framework
被自动添加为目标依赖项、链接的框架和嵌入的框架,它在复制文件构建阶段中,这是在模拟器和设备上构建所需的全部内容。
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 响应图像序列化器支持各种图像类型,包括
application/octet-stream
- 作为 AWS 等未提供真实类型的回退。image/avif
- 在 2022 年及更高版本的操作系统上,除了 watchOS。image/bmp
image/gif
image/heic
, image/heif
- 在 2017 年及更高版本的操作系统上。image/ico
image/jp2
image/jpeg
image/jpg
image/jxl
- 在 2023 年及更高版本的操作系统上。image/png
image/tiff
image/webp
- 在 2020 年及更高版本的操作系统上,除了 tvOS 和 watchOS。image/x-bmp
image/x-icon
image/x-ms-bmp
image/x-win-bitmap
image/x-xbitmap
如果您尝试下载的图像是不在列表中的无效 MIME 类型,则可以使用
DataRequest
类型上的addAcceptableImageContentTypes
扩展来添加自定义可接受的内容类型。
有几个 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")
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
类负责在优先级队列上并行下载图像。 它使用内部 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
闭包之前超出范围。
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
结合使用了 URLCache
和 AutoPurgingImageCache
,创建了一个非常强大、高性能的图像缓存系统。
URLCache
用于缓存从服务器下载的所有原始图像内容。 默认情况下,它被初始化为具有 20 MB 的内存容量和 150 MB 的磁盘容量。 这允许在任何给定时间在磁盘上存储最多 150 MB 的原始图像数据。 虽然这些默认值已经过仔细设置,但非常重要的是要考虑应用程序的需求和性能要求,以及这些值是否适合您。
如果您希望禁用此缓存层,请创建一个自定义
URLSessionConfiguration
,并将urlCache
属性设置为nil
,并在初始化ImageDownloader
时使用该配置。
ImageCache
用于缓存从服务器下载后所有可能经过滤的图像内容。 这允许缓存同一图像的多个变体,而不必每次需要时都将图像滤镜重新应用于原始图像。 默认情况下,AutoPurgingImageCache
被初始化为具有 100 MB 的内存容量和 60 MB 的首选清除后内存使用限制。 这允许在给定时间在内存中存储最多 100 MB 的最近访问过的过滤图像内容。
确定 URLCache
和 AutoPurgingImageCache
的理想内存和磁盘容量限制需要一些预见性。 您必须仔细考虑应用程序的需求,并相应地调整限制。 默认情况下,缓存组合提供以下存储容量
如果您不使用图像滤镜,建议将
URLCache
的内存容量设置为零。 否则,您会将原始图像数据存储在 URLCache 的内存存储以及 AlamofireImage 的内存存储中。
有时,应用程序逻辑最终可能会在初始下载请求完成之前尝试多次下载图像。 最常见的是,这会导致图像被多次下载。 AlamofireImage 通过合并重复下载来优雅地处理这种情况。 图像只会下载一次,但会调用两个完成处理程序。
除了合并重复下载外,AlamofireImage 还可以合并重复的图像滤镜。 如果两个具有相同标识符的图像滤镜附加到同一个下载,则图像滤镜仅执行一次,并且使用相同的生成图像调用两个完成处理程序。 对于计算量大的滤镜(例如利用 CoreImage 的滤镜),这可以节省大量时间和资源。
有时,出于各种原因,需要取消图像下载。 AlamofireImage 可以通过利用 RequestReceipt
类型以及 cancelRequestForRequestReceipt
方法,在 ImageDownloader
中智能地处理取消逻辑。 每个下载请求都会提供一个 RequestReceipt
,稍后可用于取消该请求。
通过使用 RequestReceipt
,通过 ImageDownloader
取消请求,AlamofireImage 能够确定如何最好地处理取消。 取消的下载将始终收到取消错误,而重复的下载则可以完成。 如果下载已在进行中,则允许完成,即使将使用取消错误调用完成处理程序。 这大大提高了显示大量图像的表和集合视图的性能。
不建议直接在
RequestReceipt
中调用request
上的cancel
。 这样做可能会导致诸如重复下载永远无法完成的问题。
UIImage 扩展、图像滤镜、图像缓存 和 图像下载器 的设计都具有灵活性和独立性,但也为 UIImageView
扩展提供了基础。 由于这些类、协议和扩展的强大支持,UIImageView
API 简洁、易于使用并包含大量功能。
使用 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 将能够扩大其影响范围,并为核心成员提供更好的法律保障。 如果您在工作中使用我们的任何库,请查看您的雇主是否有兴趣捐款。 您今天可以捐赠的任何金额都将不胜感激,以帮助我们实现我们的目标。
AlamofireImage 在 MIT 许可证下发布。 有关详细信息,请参见 LICENSE。