如何在 SwiftUI 中加载多个图像?
How do I load multiple images in SwiftUI?
目前我有一个从 url 加载图像的图像加载器。但是所有的图像都是一样的。有谁知道我做错了什么?
@State var outfitimage: UIImage?
// .... a lot of lines in between .....
LazyVGrid(columns: columns, spacing: 20) {
ForEach(data, id: \.id) { item in
VStack {
Text(item.displayname.capitalized)
.font(.title3)
Image(uiImage: outfitimage!)
.resizable()
.cornerRadius(15)
}
.onAppear{
downloadimage(imagename: item.user)
}
}
}
// .... a lot of lines in between ....
func downloadimage(imagename: String) {
let userimage = "outfits/" + (imagename) + ".jpg"
Storage.storage().reference().child(userimage).getData(maxSize: 1048576) {
(imageDataMyOutfit, Error) in
if let Error = Error {
print("an error accured: " + Error.localizedDescription)
} else {
if let imageDataMyOutfit = imageDataMyOutfit {
self.outfitimage = UIImage(data: imageDataMyOutfit)
} else {
print("couldn't unwrap image data")
}
}
}
}
它使用存储所有图像的 Firebase 存储。我真的不知道我做错了什么。
您只有一个带有 UIImage
的 @State 变量,因此每次从您的 downloadimage
函数加载新图像时,它都会覆盖那个值。
您可以通过几种方式解决此问题:
使用 imagename
的键(您当前传递给 download image
的值和 UIImage
的值创建一个字典。然后,动态拉动来自那本字典。我还考虑将所有这些移动到 ObservableObject
使用保持其加载状态的@State 变量将每个图像封装在其自己的子视图中。
第一个版本可能是这样的:
class ImagesLoader : ObservableObject {
@Published var images : [String:UIImage] = [:]
func downloadImage(imagename: String) {
let userimage = "outfits/" + (imagename) + ".jpg"
if self.images[imagename] != nil { return }
Storage.storage().reference().child(userimage).getData(maxSize: 1048576) {
(imageDataMyOutfit, Error) in
if let Error = Error {
print("an error accured: " + Error.localizedDescription)
} else {
if let imageDataMyOutfit = imageDataMyOutfit, let uiImage = UIImage(data: imageDataMyOutfit) {
DispatchQueue.main.async {
self.images[imagename] = uiImage
}
} else {
print("couldn't unwrap image data")
}
}
}
}
}
struct ContentView: View {
@StateObject var imagesLoader = ImagesLoader()
var body: some View {
LazyVGrid(columns: columns, spacing: 20) {
ForEach(data, id: \.id) { item in
VStack {
Text(item.displayname.capitalized)
.font(.title3)
if let uiImage = imagesLoader.images[item.user] {
Image(uiImage: uiImage)
.resizable()
.cornerRadius(15)
}
}
.onAppear{
imagesLoader.downloadImage(imagename: item.user)
}
}
}
}
}
请注意,除非有图像,否则我不会显示 Image
视图。在您当前的代码中,通过使用 !
强制展开 UIImage?
,如果它曾经是 nil
.
,您将导致崩溃
另外值得指出的是,在现实世界的情况下,您可能想要对图像进行更多缓存、错误处理等。您可以研究一个框架来执行此操作,例如 https://github.com/SDWebImage/SDWebImageSwiftUI
目前我有一个从 url 加载图像的图像加载器。但是所有的图像都是一样的。有谁知道我做错了什么?
@State var outfitimage: UIImage?
// .... a lot of lines in between .....
LazyVGrid(columns: columns, spacing: 20) {
ForEach(data, id: \.id) { item in
VStack {
Text(item.displayname.capitalized)
.font(.title3)
Image(uiImage: outfitimage!)
.resizable()
.cornerRadius(15)
}
.onAppear{
downloadimage(imagename: item.user)
}
}
}
// .... a lot of lines in between ....
func downloadimage(imagename: String) {
let userimage = "outfits/" + (imagename) + ".jpg"
Storage.storage().reference().child(userimage).getData(maxSize: 1048576) {
(imageDataMyOutfit, Error) in
if let Error = Error {
print("an error accured: " + Error.localizedDescription)
} else {
if let imageDataMyOutfit = imageDataMyOutfit {
self.outfitimage = UIImage(data: imageDataMyOutfit)
} else {
print("couldn't unwrap image data")
}
}
}
}
它使用存储所有图像的 Firebase 存储。我真的不知道我做错了什么。
您只有一个带有 UIImage
的 @State 变量,因此每次从您的 downloadimage
函数加载新图像时,它都会覆盖那个值。
您可以通过几种方式解决此问题:
使用
imagename
的键(您当前传递给download image
的值和UIImage
的值创建一个字典。然后,动态拉动来自那本字典。我还考虑将所有这些移动到ObservableObject
使用保持其加载状态的@State 变量将每个图像封装在其自己的子视图中。
第一个版本可能是这样的:
class ImagesLoader : ObservableObject {
@Published var images : [String:UIImage] = [:]
func downloadImage(imagename: String) {
let userimage = "outfits/" + (imagename) + ".jpg"
if self.images[imagename] != nil { return }
Storage.storage().reference().child(userimage).getData(maxSize: 1048576) {
(imageDataMyOutfit, Error) in
if let Error = Error {
print("an error accured: " + Error.localizedDescription)
} else {
if let imageDataMyOutfit = imageDataMyOutfit, let uiImage = UIImage(data: imageDataMyOutfit) {
DispatchQueue.main.async {
self.images[imagename] = uiImage
}
} else {
print("couldn't unwrap image data")
}
}
}
}
}
struct ContentView: View {
@StateObject var imagesLoader = ImagesLoader()
var body: some View {
LazyVGrid(columns: columns, spacing: 20) {
ForEach(data, id: \.id) { item in
VStack {
Text(item.displayname.capitalized)
.font(.title3)
if let uiImage = imagesLoader.images[item.user] {
Image(uiImage: uiImage)
.resizable()
.cornerRadius(15)
}
}
.onAppear{
imagesLoader.downloadImage(imagename: item.user)
}
}
}
}
}
请注意,除非有图像,否则我不会显示 Image
视图。在您当前的代码中,通过使用 !
强制展开 UIImage?
,如果它曾经是 nil
.
另外值得指出的是,在现实世界的情况下,您可能想要对图像进行更多缓存、错误处理等。您可以研究一个框架来执行此操作,例如 https://github.com/SDWebImage/SDWebImageSwiftUI