URLImage 2.2.5

URLImage 2.2.5

Dmytro Anokhin 维护。



URLImage 2.2.5

  • 作者
  • Dmytro Anokhin

URLImage

Follow me on Twitter

URLImage 是一个 SwiftUI 视图,用于显示从提供的 URL 下载的图像。 URLImage 为您管理来自远程位置的图像下载并本地缓存,包括内存和网络磁盘缓存。

使用 URLImage 非常简单

URLImage(url: url) { image in
    image
        .resizable()
        .aspectRatio(contentMode: .fit)
}

查看 演示应用 中的示例。

目录

特性

  • SwiftUI 的远程图像视图;
  • 本地图像缓存;
  • 完全可定制,包括占位符、进度指示、错误和处理图像视图;
  • 控制多个下载方面以获得更好的性能。

安装

URLImage 可以使用 Swift Package Manager 或 CocoaPods 进行安装。

使用 Swift 包管理器

使用包 URL 搜索 URLImage 包:[https://github.com/dmytro-anokhin/url-image](https://github.com/dmytro-anokhin/url-image)。

有关如何集成包依赖项,请参阅 将包依赖项添加到您的应用程序 文档。

使用 Cocoa Pods

URLImage 添加到您的 Podfile。

pod 'URLImage'

有关为项目设置 Cocoa Pods 的信息,请参阅 [https://cocoapods.org.cn](https://cocoapods.org.cn)。

使用

基础知识

URLImage 预期图像的 URL 和内容视图

import URLImage // Import the package module

URLImage(url: url,
         content: { image in
             image
                 .resizable()
                 .aspectRatio(contentMode: .fit)
         })

状态

URLImage 在 4 个状态之间进行转换

  • 空状态,表示尚未开始下载或没有内容可显示;
  • 进行中的状态,用于指示下载过程;
  • 失败状态,如果发生错误;
  • 内容,用于显示图像。

每种状态都有一个单独的视图,可以使用闭包提供。您还可以使用 URLImageOptions 来自定义某些设置,例如缓存策略和过期间隔。

struct MyView: View {

    let url: URL
    let id: UUID

    init(url: URL, id: UUID) {
        self.url = url
        self.id = id

        formatter = NumberFormatter()
        formatter.numberStyle = .percent
    }
    
    private let formatter: NumberFormatter // Used to format download progress as percentage. Note: this is only for example, better use shared formatter to avoid creating it for every view.
    
    var body: some View {
        URLImage(url: url,
                 options: URLImageOptions(
                    identifier: id.uuidString,      // Custom identifier
                    expireAfter: 300.0,             // Expire after 5 minutes
                    cachePolicy: .returnCacheElseLoad(cacheDelay: nil, downloadDelay: 0.25) // Return cached image or download after delay 
                 ),
                 empty: {
                    Text("Nothing here")            // This view is displayed before download starts
                 },
                 inProgress: { progress -> Text in  // Display progress
                    if let progress = progress {
                        return Text(formatter.string(from: progress as NSNumber) ?? "Loading...")
                    }
                    else {
                        return Text("Loading...")
                    }
                 },
                 failure: { error, retry in         // Display error and retry button
                    VStack {
                        Text(error.localizedDescription)
                        Button("Retry", action: retry)
                    }
                 },
                 content: { image in                // Content view
                    image
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                 })
    }
}

图片信息

如果您需要获取图片信息,例如大小,或访问下层的 CGImage 对象,可以使用 init(url: URL, content: @escaping (_ image: Image, _ info: ImageInfo) -> Content) 初始化器。

缓存

URLImage 使用了两个缓存

  • 内存缓存,用于快速访问;
  • 本地磁盘缓存。

下载的图片存储在用户缓存文件夹中。这允许操作系统负责清理文件。定期手动清理也是一个好主意。

您可以通过在启动过程中调用 cleanup 来删除已过期的图片。如果您使用过之前的 URLImage 版本,它还将删除图片文件。

URLImageService.shared.cleanup()

下载的图片经过一段时间后就会过期。过期的图片会在 cleanup 程序中删除。过期间隔可以使用 URLImageOptionsexpiryInterval 属性来设置。

您还可以使用 URLImageService 删除单个或所有缓存的图片。

使用 URLCache

或者,您可以使用 URLCache。您可以全局配置包,也可以按视图配置。

URLImageService.shared.defaultOptions.cachePolicy = .useProtocol

// Download using `URLSessionDataTask` 
URLImageService.shared.defaultOptions.loadOptions.formUnion(.inMemory)

// Set your `NSURLRequest.CachePolicy`
URLImageService.shared.defaultOptions.urlRequestConfiguration.cachePolicy = .returnCacheDataElseLoad

使用 URLCache 添加了对 Cache-Control 头的支持。作为权衡,您会失去一些控制,例如内存缓存、下载延迟、过期间隔(您可以通过Cache-Control 头获得)。它也只适用于内存下载(使用 URLSessionDataTask)。

选项

URLImage 允许您通过 URLImageOptions 结构控制下载和缓存的各个方面。您可以使用 URLImageService.shared.defaultOptions 属性设置默认选项。以下是主要设置:

identifier: String?

默认情况下,图片通过其 URL 识别。作为替代,您还可以提供一个字符串标识符来覆盖此设置。

expiryInterval: TimeInterval?

缓存图片在此时间间隔后过期,并可被删除。图片会作为在 缓存 段落中描述的清理程序的一部分被删除。

maxPixelSize: CGSize?

解码图像的最大像素尺寸。如果没有指定此属性,则解码图像的宽度和高度不受限制,可能与图像本身一样大。

cachePolicy: CachePolicy

缓存策略控制从缓存中加载图像的方式。

缓存策略

缓存策略,类型为 URLImageOptions.CachePolicy,允许指定 URLImage 如何利用缓存,类似于 NSURLRequest.CachePolicy。此类型还可以指定访问磁盘缓存和开始下载的延迟。

returnCacheElseLoad

从缓存返回图像或下载它。

returnCacheDontLoad

从缓存返回图像,不下载它。

ignoreCache

忽略缓存图像并下载远程图像。


一些选项可以使用 URLImageService.shared.defaultOptions 属性全局设置。下列选项是默认设置的

  • `expireAfter` 为 24 小时;
  • `cachePolicy` 为 `returnCacheElseLoad`,且无延迟;
  • `maxPixelSize` 为 1000 x 1000 像素(watchOS 为 300 x 300 像素)。

获取图像

您可能希望在没有任何视图的情况下下载图像。这可以通过使用 RemoteImagePublisher 对象来实现。`RemoteImagePublisher` 可以缓存图像供 `URLImage` 视图未来使用。

下载图像为 CGImage 并忽略任何错误

cancellable = URLImageService.shared.remoteImagePublisher(url)
    .tryMap { $0.cgImage }
    .catch { _ in
        Just(nil)
    }
    .sink { image in
        // image is CGImage or nil
    }

作为 [CGImage?] 数组下载多个图像

let publishers = urls.map { URLImageService.shared.remoteImagePublisher($0) }

cancellable = Publishers.MergeMany(publishers)
    .tryMap { $0.cgImage }
    .catch { _ in
        Just(nil)
    }
    .collect()
    .sink { images in
        // images is [CGImage?]
    }

当使用 `RemoteImagePublisher` 对象下载图像时,所有选项都适用,就像为 `URLImage` 对象那样。默认情况下,下载的图像将在磁盘上缓存。这可以加快在应用后期显示图像的速度。此外,这目前是 iOS 14 小部件中显示图像的唯一支持方式。

在 iOS 14 小部件中下载图像

不幸的是,WidgetKit 中的视图无法运行异步操作:[Apple 开发者论坛](https://developer.apple.com/forums/thread/652581)。建议的方式是在 TimelineProvider 中加载数据,包括图像。

您仍然可以使用 URLImage 来做这件事。想法是在 TimelineProvider 中使用 RemoteImagePublisher 对象加载图像,并在 URLImage 视图中显示它。

报告一个虫子

使用GitHub issue来报告虫子。当可能时,请包含以下信息。

总结和/或背景;操作系统和您使用的设备;URLImage库的版本;您期望发生的事情;实际发生的事情;其他信息:展示bug的截图或视频;崩溃日志;示例代码,请尝试在无依赖项的情况下编译;测试数据:如果您使用公共资源,请提供图片的URL。

请确保有一个可复现的场景。理想情况下,请提供示例代码。如果您提交了示例代码,请确保它能够编译 ;)

请求新特性

使用GitHub issues来请求新特性。

贡献

欢迎贡献。在提交拉取请求之前,请先创建GitHub issue以规划并讨论实现。