我正在从 Firebase 检索练习列表并对其进行过滤。之后,我需要发出另一个异步请求来解析视频 URL 并更新它(请参阅下面的代码)。问题是练习在 URL 解析之前返回到视图。怎么解决?
import Combine
import FirebaseStorage
import Foundation
class ExerciseViewModel<DS: DataService>: ObservableObject where DS.Item == Exercise {
@Published var exercises: [Exercise] = []
private let dataService: DS
private let storage = Storage.storage(url: "someURL")
private var cancellables = Set<AnyCancellable>()
init(dataService: DS, idArray: [String]) {
self.dataService = dataService
dataService.getData()
.sink { error in
print("Exercises request failed: \(String(describing: error))")
} receiveValue: { [weak self] data in
Task {
self?.exercises =
await self?.filterExercises(exercises: data, by: idArray) ?? []
}
}
.store(in: &cancellables)
}
private func filterExercises(exercises: [Exercise], by idArray: [String]) async -> [Exercise] {
var filteredExercises = exercises.filter { idArray.contains($0.id ?? "") }
filteredExercises.forEach {
var exercise = $0
Task {
do {
exercise.videoUrl = try await self.storage.reference().child(
"video/\(exercise.video ?? "")"
).downloadURL().absoluteString
print("Video URL resolved: \(exercise.videoUrl ?? "")")
} catch { print("Error resolving video URL: \(error)") }
}
}
return filteredExercises
}
}
更新了代码以使其正常工作:
init(dataService: DS, idArray: [String]) {
self.dataService = dataService
dataService.getData()
.sink { error in
print("Exercises request failed: \(String(describing: error))")
} receiveValue: { [weak self] data in
Task {
self?.exercises = await self?.filterExercises(exercises: data, by: idArray) ?? []
}
}
.store(in: &cancellables)
}
private func filterExercises(exercises: [Exercise], by idArray: [String]) async -> [Exercise] {
let filteredExercises = exercises.filter{idArray.contains($0.id ?? "")}
var result: [Exercise] = []
for exercise in filteredExercises {
let videoUrl = await getVideoRef(exercise.video ?? "")
var updatedExercise = exercise
updatedExercise.videoUrl = videoUrl
result.append(updatedExercise)
}
return result
}
private func getVideoRef(_ video: String) async -> String {
do {
let videoURL = try await storage.reference().child("video/\(video)").downloadURL().absoluteString
return videoURL
} catch { return "" }
}