显示问题的更短示例代码:
带有@published var 和 fetch 函数的 DataManager
class DataManager {
static let instance = DataManager()
let apiKey: String = "c2e5cb16"
@Published var fetchedSPIDERMAN: SearchModel = SearchModel(search: nil, totalResults: nil, response: nil)
var cancelFetchAllSelections = Set<AnyCancellable>()
private init() {
fetchSpiderman()
}
func fetchSpiderman() {
guard let url = URL(string: "https://www.omdbapi.com/?apikey=\(apiKey)&s=spider") else { return print("MY ERROR: BAD URL") }
NetworkingManager.download(url: url)
.decode(type: SearchModel.self, decoder: JSONDecoder())
.sink(receiveCompletion: NetworkingManager.handleCompletion,
receiveValue: { [weak self] (moviesDownloaded) in
self?.fetchedSPIDERMAN = moviesDownloaded
print("fetchedSPIDER")
})
.store(in: &cancelFetchAllSelections)
}
}
ViewModel 与其他@published var 和 func .sink
class ViewModel: ObservableObject {
let dataService = DataManager.instance
var selectionForSpiderman: [MovieModel] = []
@Published var cancellables = Set<AnyCancellable>()
init() {
}
func sinkToSelectionForSpiderman(){
dataService.$fetchedSPIDERMAN
.receive(on: DispatchQueue.main)
.sink { [weak self] (fetchedMovieModel) in
if let unwrappedFetchedMovieModel = fetchedMovieModel.search {
self?.selectionForSpiderman = unwrappedFetchedMovieModel
}else {
print("MY ERROR: CANT SINK SPIDERMAN")
}
}
.store(in: &cancellables)
}
} !!! 在控制台中,它显示打印(“我的错误:无法击沉蜘蛛侠”),您可以在 VIEWMODEL 屏幕截图中看到 !!!
带有 .onApear 的 HomeView 调用 vm.sinkToSelectionSpiderman()
struct HomeView: View {
@StateObject var vm: ViewModel = ViewModel()
let randomUrl: String = "https://media.istockphoto.com/id/525982128/cs/fotografie/agresivita-koček.jpg?s=1024x1024&w=is&k=20&c=y632ynYYyc3wS5FuPBgnyXeBNBC7JmjQNwz5Vl_PvI8="
var body: some View {
ScrollView(.horizontal, showsIndicators: true) {
HStack(spacing: 0) {
ForEach(vm.selectionForSpiderman) { selection in
VStack(alignment: .leading, spacing: 12) {
AsyncImage(url: URL(string: selection.poster ?? randomUrl)) { returnedImage in
switch returnedImage {
case .empty:
ProgressView()
case .success (let image):
image
.resizable()
.frame(width: 200,
height: 120,
alignment: .leading)
.background(Color.red)
.scaledToFill()
.cornerRadius(10)
.shadow(color: Color.white.opacity(0.2), radius: 5, x: 0, y: 5)
case .failure (_):
Image(systemName: "xmark")
default:
Image(systemName: "xmark")
}
}
Text(selection.title ?? "NA")
.foregroundColor(Color.white)
.font(.system(.headline, design: .rounded, weight: .medium))
.padding(.leading, 12)
}.frame(maxWidth: 210)
}
.accentColor(Color.white)
}
}
.onAppear {
vm.sinkToSelectionForSpiderman()
}
}
}
我的模型通常与其他 Fetch 函数一起工作。
主要问题是: 我很确定我需要在 Fetch func 之后调用 .sink func ...但是如果 .onAppear 代码块在 Fetch func 完成之前执行并且有时间将数据发送给订阅者 .sink func?
有趣的事实: 一旦它实际在 Canvas 的 scrollView 中显示了数据:不幸的是,DD 只是一次,再也不会了。也许 API 很慢
我试图查看 SwiftUI 中的计时如何工作以及何时调用哪个函数,但它太具体了,我没有找到答案。如果你知道我可以研究这类东西的任何资源,请告诉我!! :)