iOS开发者经常会遇到需要在应用中显示网络图像的场景,无论是获取和显示用户头像,展示产品图像,等等。在原来的UIKit
中,如果我们要用系统的API
还是稍微有点麻烦,很多开发的朋友都选择了第三方的框架去处理网络图片的请求缓存等等。
AsyncImage
是SwiftUI
中一个强大的功能,它简化了在应用程序中异步加载和显示网络图像的过程。使用AsyncImage
,可以无缝地处理图像加载,缺省视图,甚至错误处理,同时保持响应式用户界面。
不过这个组件需要iOS 15.0
,tvOS 15.0
及以上的版本才能使用。
AsyncImage基本使用
AsyncImage
使用共享的URLSession
实例从指定的URL
加载图像,然后显示它。例如:
AsyncImage
最简单的使用方法就是只传入一个url,便会异步去加载这张图片,在图片加载出来之前,整个组件背景色为淡灰色,也可以认为缺省图就是一个淡灰色的背景。
我们也可以对AsyncImage
添加很多的修饰符,比如background
,cornerRadius
等等,如果修改了background
,那么在图片加载出来之前显示的就是这个设置的background
。
struct AsyncImageDemo: View {
private let photoURL = URL(string: "https://picsum.photos/200")
var body: some View {
AsyncImage(url: photoURL)
.frame(width: 200, height: 200)
.background(Color.red)
.cornerRadius(20)
.shadow(color: .black.opacity(0.6) ,radius: 20, y: 10)
}
}
placeholder
很多的时候我们都会设置图片在未加载完的显示内容,这不仅限于一个缺省的默认颜色,在加载图片时显示缺省视图可以显著增强用户体验。特别是在网络图像可能需要一些时间来获取的情况下。
通过下面的初始化方法,我们可以自定义缺省图。如果在加载时发生错误,将显示相同的缺省图。
struct AsyncImageDemo: View {
private let photoURL = URL(string: "https://picsum.photos/200")
var body: some View {
AsyncImage(url: photoURL) { image in
image
.resizable()
.background(Color.red)
.cornerRadius(20)
.shadow(color: .black.opacity(0.6) ,radius: 20, y: 10)
} placeholder: {
ProgressView()
.progressViewStyle(.circular)
}
.frame(width: 200, height: 200)
}
}
上面初始化方法里,第一个闭包返回了一个Image
实例,我们可以对这个Image
添加很多的修饰符。
第二个闭包里面就可以设置缺省图,这里显示了一个ProgressView
组件,也可以设置为一个颜色组件,那就和基础用法里的一样了。
另外添加frame
修饰符的时候,可以添加给Image
,也可以添加给AsyncImage
,区别就在于修饰的范围大小,添加给AsyncImage
,那么ProgressView
也是该尺寸。
处理请求error
如果想要获得对加载过程的更多控制,可以使用init(url:scale:transaction:content:)
初始化方法,它接受一个内容闭包,该闭包返回一个AsyncImagePhase
来指示加载操作的状态,返回一个适合当前阶段的视图:
AsyncImagePhase
是一个枚举,它代表了图片加载的每个阶段:
@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *)
public enum AsyncImagePhase : Sendable {
/// No image is loaded.
case empty
/// An image succesfully loaded.
case success(Image)
/// An image failed to load with an error.
case failure(any Error)
/// The loaded image, if any.
///
/// If this value isn't `nil`, the image load operation has finished,
/// and you can use the image to update the view. You can use the image
/// directly, or you can modify it in some way. For example, you can add
/// a ``Image/resizable(capInsets:resizingMode:)`` modifier to make the
/// image resizable.
public var image: Image? { get }
/// The error that occurred when attempting to load an image, if any.
public var error: (any Error)? { get }
}
AsyncImage(url: photoURL, transaction: Transaction(animation: .easeInOut)) { phase in
switch phase {
case .empty:
ProgressView()
.progressViewStyle(.circular)
case .success(let image):
image
.resizable()
.transition(.scale(scale: 0.1, anchor: .center))
case .failure:
Image(systemName: "questionmark.diamond")
.imageScale(.large)
@unknown default:
EmptyView()
}
}
.frame(width: 200, height: 200)
在闭包内,通过switch
判断来决定每个阶段要显示的内容。
该初始化方法中还传入了transaction
参数,它需要传入一个Transaction
实例,用来决定AsyncImagePhase
每个阶段的转场动画。
除了用switch
判断每个阶段,也可以直接判断是否得到了图片或者error等,比如下面的代码:
struct AsyncImageDemo: View {
private let photoURL = URL(string: "https://picsum.photos/200")
var body: some View {
AsyncImage(url: photoURL) { phase in
if let image = phase.image {
// Displays the loaded image.
image
.resizable()
.cornerRadius(20)
.shadow(color: .black.opacity(0.6) ,radius: 20, y: 10)
} else if phase.error != nil {
// Displays error view
Image(systemName: "questionmark.diamond")
.imageScale(.large)
} else {
// Displays loading view
ProgressView()
.progressViewStyle(.circular)
}
}
.frame(width: 200, height: 200)
}
}
写在最后
本篇文章主要介绍了如何使用AsyncImage
视图下载和显示网络图像,这个组件大大的简化了我们加载网络图片的代码和相关的逻辑。
最后,希望能够帮助到有需要的朋友,如果您觉得有帮助,还望点个赞,添加个关注,笔者也会不断地努力,写出更多更好用的文章。
标签:200,异步,image,缺省,AsyncImage,SwiftUI,Image,加载 From: https://blog.csdn.net/guoyongming925/article/details/139313402