Swift api observable 没有等待就无法工作

Swift api observable not working without wait

您好,我正在 LocationsDataService class 中从本地 api 获取数据,并将其分配为数据服务中的 @Published var,然后在我的 LocationsViewModel。例如,如果我等待 api 请求完成;

 DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
            let locations = dataService.locations
            self.locations = locations
        }

然后位置会呈现在屏幕上。

这是我的数据服务class;

//
//  LocationsDataService.swift
//  MapTest
//
//

import Foundation
import MapKit
import Combine

class LocationsDataService: ObservableObject {
    
    let token = "2|asOnUG27uCrcVuGxOO65kS25mX0nUSls5ApfemQy";
    @Published var locations: [Location] = []
    public var cancellable: AnyCancellable?
    enum HTTPError: LocalizedError {
        case statusCode
    }
    
    init() {
        fetch()
    }
    
    func fetch() {
        
        guard let url = URL(string: "http://localhost:8080/api/locations") else {
            print("Invalid url...")
            return
        }
        var urlRequest = URLRequest(
            url: url
        )
        urlRequest.setValue(
            "Bearer \(token)",
            forHTTPHeaderField: "Authorization"
        )
        
        self.cancellable = URLSession.shared.dataTaskPublisher(for: urlRequest)
                .tryMap { output in
                    guard let response = output.response as? HTTPURLResponse, response.statusCode == 200 else {
                        throw HTTPError.statusCode
                    }
                    return output.data
                }
                .decode(type: [Location].self, decoder: JSONDecoder())
                .receive(on: DispatchQueue.main)
                .eraseToAnyPublisher()
                .sink(receiveCompletion: { completion in
                    switch completion {
                    case .finished:
                        break
                    case .failure(let error):
                        fatalError(error.localizedDescription)
                    }
                }, receiveValue: { locations in
                    self.locations = locations
                })
        
    }
    
}

这是我的视图模型

//
//  LocationsViewModel.swift
//  CoffeeShops
//
//

import Foundation
import MapKit
import SwiftUI

class LocationsViewModel: ObservableObject {
    
    // all loaded locations
    @Published var locations: [Location]
    
   
    init() {
        let dataService = LocationsDataService() // the init function will do the api call
        
        self.locations = [Location(
            name: "Amsterdam",
            address: "Amsterdam",
            latitude: 52.3721009,
            longitude:  4.8912196,
            description: "Amsterdam",
            imageNames: [],
            link: "https://en.wikipedia.org/wiki/Colosseum")]
        

        DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
            let locations = dataService.locations
            self.locations = locations
            print(locations)
        }
        
    }
    

}

我不确定为什么在将 api 分配给 LocationsViewModel 中的位置之前需要明确等待 api,因为 LocationsDataService.locations@Published var locations: [Location] = [],因此我认为它会被观察到。显然,在我可以更新屏幕之前设置一个时间限制并不是很好,因为它可以在 1 秒或 5 秒内完成。知道我做错了什么吗?

ObservableObject 将使 SwiftUI 视图在 @Published 更改时更新视图。但是当你在另一个里面创建一个 ObservableObject 时,它不可能自动工作。

您实际上不需要 ObservableObject 来提供您的服务,您只需要 @Published 来提供您的服务 属性,并且您可以如何将它与您的视图模型同步:

private var cancellable: AnyCancellable?

init() {
    cancellable = dataService.$locations.sink(receiveValue: { locations in
        self.locations = locations
    })
}