Быстрое обнаружение конца синтаксического анализа json

#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.