#json #swift #swiftui
#json #быстрый #swiftui #быстрое
Вопрос:
Я анализирую определенные данные URL-адреса json для отображения на карте, и мне нужно определить, что у меня есть все данные для отображения счетчика, пока ничего не происходит. Я создал переменную, которая переходит из false в true после того, как у меня есть все данные, но эта переменная существует только как true внутри цикла for Это часть кода, который получает данные
import SwiftUI
import MapKit
var locationsFillTest : Int = 0
var allLocations = [MKPointAnnotation]()
var doneGettingData : Bool = false
struct MapView: UIViewRepresentable {
var startdate : String
func makeUIView(context: Context) -> MKMapView{
MKMapView(frame: .zero)
}
func makeCoordinator() -> MapViewCoordinator{
MapViewCoordinator(self)
}
func updateUIView(_ uiView: MKMapView, context: Context){
uiView.removeAnnotations(allLocations)
allLocations = []
doneGettingData = false
print("Done = (doneGettingData)")
let url = URL(string: "https://XXXXXX")!
URLSession.shared.dataTask(with: url) {(data,response,error) in
do {
if let d = data {
let decodedLists = try JSONDecoder().decode(emsc.self, from: d)
DispatchQueue.main.async {
locationsFillTest = allLocations.count
doneGettingData = false
for locations in decodedLists.features {
let lat = Double(locations.properties.lat)
let long = Double(locations.properties.lon)
let annotation = MKPointAnnotation()
annotation.coordinate = CLLocationCoordinate2D(latitude: lat , longitude: long )
if locationsFillTest == 0 {
allLocations.append(annotation)}
}
uiView.addAnnotations(allLocations)
uiView.delegate = context.coordinator
uiView.showAnnotations(allLocations, animated: true)
doneGettingData = true
print("Done = (doneGettingData)")
}
}else {
print("No Data")
}
} catch {
print("Error decoding JSON: ", error, response!)
}
}.resume()
}
}
Переменная doneGettingData становится ложной и истинной при просмотре печати, но если мне нужно использовать ее, например, для создания счетчика, она всегда будет ложной, поскольку она является единственной истинной внутри.
Как я могу сделать это глобальным ?
Спасибо
Ответ №1:
Если у вас нет другого объявления для doneGettingData
внутри закрытия, для свойства уровня экземпляра устанавливается значение true. Возможно, оно устанавливается позже, чем вы ожидаете. Попробуйте следующее, чтобы увидеть, когда оно изменится (и настроить вас на реакцию на эти изменения):
var doneGettingData : Bool = false {
didSet {
if doneGettingData {
print("The instance property doneGettingData is now true.")
} else {
print("The instance property doneGettingData is now false.")
}
}
}
Возможно, вы захотите превратить это в пользовательское перечисление, хотя и со случаями, подобными fetching
, done
, noData
и jsonError
. Прямо сейчас, если данных нет, у вас никогда не будет триггера для повторной попытки, перехода дальше, уведомления пользователя и т.д. То же самое относится и к ошибке декодирования. Или, по крайней мере, установите флаг в значение true в самом конце цикла, чтобы что-то происходило, несмотря ни на что.
Что-то вроде:
enum DataCollectionState {
case fetching, done, noData, jsonError
var doneGettingData : DataCollectionState = fetching {
didSet {
switch doneGettingData {
case fetching:
// Show a spinner or something
case done:
// Hide the spinner
case noData:
// Tell the user there was no data? Try again?
case jsonError:
// Tell the user there was an error? Try again?
}
}
}
Примечание: у меня сейчас не открыт Xcode, поэтому синтаксис может быть неточным.
Комментарии:
1. Спасибо — если я воспользуюсь вашим предложением, оно изменится, так что на самом деле переменная меняется, но в contentView ( SwiftUI) просто для проверки, если я сделаю это: Text(doneGettingData.description) его false, чем он изменится на true и никогда не изменится снова на false и true, когда я изменяю, например, один из параметров, который заставляет получать новый Json.