从url异步加载SwiftUI中的多个图像
我正在尝试编写一个代码,从url加载多个图像(介于5到10之间)。我使用AudioDB api(加载的图像是艺术家的照片)。问题是只显示最后一张图像。在ContentView中,我有一个ForEach,它可以加载5到10个ArtistImage(s)结构。我知道所有图像数据都已加载(在ImageFetcher var imageData中,将设置I put print(新值),并显示已加载的数据(例如:148273字节等)。只是无法理解为什么只显示最后一个图像从url异步加载SwiftUI中的多个图像,swift,xcode,image,swiftui,imageurl,Swift,Xcode,Image,Swiftui,Imageurl,我正在尝试编写一个代码,从url加载多个图像(介于5到10之间)。我使用AudioDB api(加载的图像是艺术家的照片)。问题是只显示最后一张图像。在ContentView中,我有一个ForEach,它可以加载5到10个ArtistImage(s)结构。我知道所有图像数据都已加载(在ImageFetcher var imageData中,将设置I put print(新值),并显示已加载的数据(例如:148273字节等)。只是无法理解为什么只显示最后一个图像 struct ArtistImag
struct ArtistImage: View {
var imageURL: URL?
@ObservedObject private var imageFetcher: ImageFetcher
init(imageURL: String) {
self.imageURL = URL(string: imageURL)
imageFetcher = ImageFetcher(imageURL: self.imageURL)
}
var body: some View {
if let uiImage = UIImage(data: imageFetcher.imageData) {
return AnyView(Image(uiImage: UIImage(data: self.imageFetcher.imageData)!)
.renderingMode(.original)
.resizable()
.cornerRadius(10))
} else {
return AnyView(Text("Loading...")
.onAppear(perform: { self.imageFetcher.getImage() }))
}
}
以及下面的ImageFetcher类:
class ImageFetcher: ObservableObject {
public let objectWillChange = PassthroughSubject<Data,Never>()
public private(set) var imageData = Data() {
willSet {
print(newValue) // it tells me all images are loaded
objectWillChange.send(newValue)
}
}
var imageURL: URL?
public init(imageURL: URL?) {
self.imageURL = imageURL
}
func getImage() {
guard let url = imageURL else { return }
URLSession.shared.dataTask(with: url) { (data, _, _) in
guard let data = data else {
return
}
DispatchQueue.main.async {
self.imageData = data
}
}.resume()
}
}
网络管理器类:
class NetworkManager: ObservableObject {
@Published var artistsDB = [Artist]()
func createArtistsDatabase() {
let artistsNames: [String] = ["Madonna", "Metallica","Coldplay","Toto","Kraftwerk","Depeche%20Mode"]
for ar in artistsNames {
findArtistBy(name: ar)
}
}
func findArtistBy(id: String = "", name: String = "") {
var url: URL?
if id != "" {
guard let urlID = URL.getArtistByID(id: id) else { return }
url = urlID
} else {
guard let urlName = URL.getArtistByName(name: name) else { return }
url = urlName
}
let urlRequest = URLRequest(url: url!)
let task = URLSession.shared.dataTask(with: urlRequest) { data,response,error in
if error != nil || data == nil {
print("Client error")
return
}
guard let response = response as? HTTPURLResponse, (200...299).contains(response.statusCode) else {
print("Server error")
return
}
guard let mime = response.mimeType, mime == "application/json" else {
print("Wrong mime type")
return
}
guard let dataToDecode = data else { return }
do {
let decoder = JSONDecoder()
let dataJSONed = try decoder.decode(DBArtist.self, from: dataToDecode)
DispatchQueue.main.async {
print(dataJSONed.artist[0])
self.artistsDB.append(dataJSONed.artist[0])
}
} catch {
print("Error while decoding!")
}
}
task.resume()
}
URL扩展名:
extension URL {
static func getArtistByID(id: String) -> URL? {
return URL(string: "https://theaudiodb.com/api/v1/json/1/artist.php?i=\((id))")
}
static func getArtistByName(name: String) ->URL? {
print("https://www.theaudiodb.com/api/v1/json/1/search.php?s=\(name)")
return URL(string: "https://www.theaudiodb.com/api/v1/json/1/search.php?s=\(name)")
}
}
是否显示ContentView代码?是的,我刚刚更新了第一篇文章。您可以共享NetworkManager吗?当然,刚刚添加。好的,我刚刚发现问题:在NetworkManager中,我将新项目添加到数组中(新艺术家到艺术家数组),这导致不断更新/刷新观察到的数据库(ArtistDB)。我将其更改为将所有数据收集到临时数组,并在收集到所有数据时将其复制到ArtistDB,从而只触发一次UI更新。
extension URL {
static func getArtistByID(id: String) -> URL? {
return URL(string: "https://theaudiodb.com/api/v1/json/1/artist.php?i=\((id))")
}
static func getArtistByName(name: String) ->URL? {
print("https://www.theaudiodb.com/api/v1/json/1/search.php?s=\(name)")
return URL(string: "https://www.theaudiodb.com/api/v1/json/1/search.php?s=\(name)")
}