嗨,我是 swift 的初學者,我正在使用 ViewModel,我正在嘗試從我在本地設定的 api 中獲取資料,如下所示;
//
// LocationsViewModel.swift
//
//
import Foundation
import MapKit
import SwiftUI
class LocationsViewModel: ObservableObject {
// all loaded locations
@Published var locations: [Location]
// Current location on map
@Published var mapLocation: Location {
didSet {
updateMapRegion(location: mapLocation)
}
}
// current region on map
@Published var mapRegion: MKCoordinateRegion = MKCoordinateRegion()
// show list of locations
@Published var showLocationsList: Bool = false
// show location detail via sheet
@Published var sheetLocation: Location? = nil
let mapSpan = MKCoordinateSpan(
latitudeDelta: 0.1,
longitudeDelta: 0.1
)
init() {
LocationsDataService.fetch()
let locations = LocationsDataService.locations
self.locations = locations
self.mapLocation = locations.first!
self.updateMapRegion(location: locations.first!)
}
private func updateMapRegion(location: Location) {
withAnimation(.easeInOut) {
mapRegion = MKCoordinateRegion(
center: location.coordinates,
span: mapSpan
)
}
}
func toggleLocationsList() {
withAnimation(.spring()) {
showLocationsList.toggle()
}
}
func showNextLocation(location: Location) {
withAnimation(.easeInOut) {
mapLocation = location
showLocationsList = false
}
}
}
但是,這在以下兩行中給我帶來了錯誤;
LocationsDataService.fetch()
let locations = LocationsDataService.locations
哪個是;
Instance member 'fetch' cannot be used on type 'LocationsDataService'; did you mean to use a value of this type instead?
Instance member 'locations' cannot be used on type 'LocationsDataService'; did you mean to use a value of this type instead?
我的資料服務如下;
//
// LocationsDataService.swift
//
import Foundation
import MapKit
class LocationsDataService {
let token = "2|asOnUG27uCrcVuGxOO65kS25mX0nUSls5ApfemQy";
@Published var locations: [Location] = []
func fetch() {
guard let url = URL(string: "http://localhost:8080/api/locations") else {
print("Invalid url...")
return
}
var urlRequest = URLRequest( //2
url: url
)
urlRequest.setValue( //3
"Bearer \(token)",
forHTTPHeaderField: "Authentication"
)
urlRequest.setValue( //4
"application/json;charset=utf-8",
forHTTPHeaderField: "Content-Type"
)
let task = URLSession.shared.dataTask(with: urlRequest) { [weak self] data, _, error in
guard let data = data, error == nil else {
return
}
do {
let apiLocations = try JSONDecoder().decode([Location].self, from: data)
DispatchQueue.main.async {
self?.locations = apiLocations
}
} catch {
print(error)
}
}
task.resume()
}
}
這是我的位置模型;
//
// Location.swift
//
//
import Foundation
import MapKit
import CoreLocation
struct Location: Identifiable, Equatable, Codable {
static func == (lhs: Location, rhs: Location) -> Bool {
return lhs.id == rhs.id
}
let name: String
let cityName: String
// let coordinates: CLLocationCoordinate2D
let description: String
let imageNames: [String]
let link: String
var id: String {
// create computed variable for id
name cityName
}
let latitude: Double
let longitude: Double
var coordinates: CLLocationCoordinate2D {
return CLLocationCoordinate2D(latitude: CLLocationDegrees(latitude), longitude: CLLocationDegrees(longitude))
}
}
任何想法如何從我的服務類中的 api 獲取資料并在 LocationsViewModel 中使用它?
uj5u.com熱心網友回復:
通過呼叫LocationsDataService.fetch(),您正在呼叫不存在的靜態函式 fetch。你需要一個實體LocationsDataService,所以基本上你需要實體化它,然后fetch()像這樣呼叫
let dataService = LocationsDataService()
dataService.fetch()
財產也是locations如此。
否則,您可以制作fetch和locations靜態,LocationsDataService但通常這是您不想要的。
uj5u.com熱心網友回復:
您的代碼中有幾個小錯誤。第一個是您正在訪問fetch()并且locations好像它們是static變數。他們不是,你需要一個服務實體,比如
let service = LocationsDataService()
那將被放在一個class水平上。但這不會像你期望的那樣作業......
fetch()是異步的,所以locations不會立即有值。由于您的使用,我建議您使用“完成處理程式”并使您的服務 astruct而不是 aclass
https://docs.swift.org/swift-book/LanguageGuide/Closures.html
話雖如此,這就是為什么...
An@Published只能在 a 內部作業,ObservableObject它不能只是 a class。
您不能鏈接ObservableObjects 并期望自己獲得更新。您需要訂閱 using.sink才能在視圖模型中獲取更新。
但是您沒有獲得多次更新,因此您無需添加訂閱,完成處理程式將為您提供一次性結果。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/425587.html
