в моем проекте. Я пытаюсь загрузить некоторые данные аэропорта через вызов API и отобразить их в списке,
пока это происходит в моем представлении SwiftUI, я хочу отобразить простую анимацию загрузки Circle.
Для обеда загрузки я использую кнопку, которая запускает действие и активирует анимацию с помощью @state (isSearching = false или true)
вот мое мнение:
import SwiftUI
struct AirportSearch: View {
@ObservedObject var dm : DataManager
@State var ICAOSearsh = ""
@State var isSearching = false
var body: some View {
ZStack {
backgroundGradiet.edgesIgnoringSafeArea(.all)
if self.isSearching == false{
LottieView(filename: "planeAnimation")
}
VStack{
CustomTextField(placeholder: Text(" Search ICAO").foregroundColor(.white), text: $ICAOSearsh)
.padding(.horizontal , 10)
.frame(height: 40.0)
.border(Color.black.opacity(5.0), width: 1)
\\ Button HERE________________________________________________________________
Button(action: {
self.isSearching = true
self.dm.searchAirportOnline(icaoCode: self.ICAOSearsh)
{
debugPrint("finito search")
self.isSearching = false
}
}) {
HStack{
Image(systemName: "magnifyingglass").foregroundColor(Color.white)
Text("Find your airport").foregroundColor(.white)
}
}
\\ button above HERE________________________________________________________
if isSearching == false{
List{
ForEach(self.dm.airportVector) { aeroporto in
VStack{
HStack{
Image(systemName: "airplane").foregroundColor(.red)
Text(aeroporto.aptShortName).bold()
Spacer()
Text(aeroporto.aptICAO)
Text("/")
Text(aeroporto.aptIATA)
}
HStack{
Text(aeroporto.countryCode)
Spacer()
Text(aeroporto.continent)
}.font(.system(size: 13))
}
.foregroundColor(.white)
}.padding(.horizontal)
}.onAppear {
UITableView.appearance().backgroundColor = UIColor.clear
UITableViewCell.appearance().backgroundColor = .clear
}
} else {
Spacer()
CircleLoading()
Spacer()
}
}
}
}
var backgroundGradiet: LinearGradient {
let gradient = LinearGradient(gradient: Gradient(colors: [Color.blue,Color.black]), startPoint: .topTrailing, endPoint: .bottomLeading)
return gradient
}
}
к сожалению когда я нажимаю кнопку, анимация останавливается.
для решения этой проблемы я пытаюсь использовать DispatchQueue.global (). asyn c {} и DispatchQueue.main.asyn c {} на мой класс DataManager, но я получаю предупреждение:
Publishing changes from background threads is not allowed; make sure to publish values from the main thread (via operators like receive(on:)) on model updates```
здесь, ниже моего класса:
import UIKit
import Combine
import SwiftUI
import CoreLocation
class DataManager: ObservableObject {
let objectWillChange = PassthroughSubject<Void,Never>()
static let shared = DataManager()
@Published var airportVector : [AirportModel] = []
{
didSet {
objectWillChange.send()
}
}
init() {
}
// MARK: - Search Online ICAO apt
func searchAirportOnline(icaoCode: String, closure : @escaping () ->()) {
DispatchQueue.global().async {
self.airportVector = [] // empty the vector to
// set the request apiKey
let headers : HTTPHeaders = [
"x-rapidapi-host": "aerodatabox.p.rapidapi.com",
"x-rapidapi-key": "18df152ef8msh5e365520639e47ep1fb24bjsn8e65c311e1f7"
]
let linkRequest = "https://aerodatabox.p.rapidapi.com/airports/icao/\(icaoCode)?withTime=true&withRunways=false"
// make request via AlamoFire
AF.request(linkRequest, method: .get, headers: headers)
.responseData { (responseData) in
switch responseData.result {
case .success(let value ) :
let json = JSON(value)
var airport = AirportModel(aptICAO: "", aptIATA: "", aptShortName: "", aptFullName: "", aptMunicipalName: "", locationLat: "", locationLon: "", countryName: "", countryCode: "", continent: "", timeZone: "", linkLiveATC: "", linkLinkFlightRadar: "", airportWebsite: "", currentTimeUTC: "", currentTimeLocal: "", runway: [RunwayModel(name1: RunwayModel.Runway(lengthM: "", lengthF: "", hasLighting: false, widthM: "", widthF: "", surface: "", isClosed: false, name: "", trueHdg: "", displacedThresholdM: "", displacedThresholdF: "", locationLat:0.0, locationLong: 0.0), name2: RunwayModel.Runway(lengthM: "", lengthF: "", hasLighting: false, widthM: "", widthF: "", surface: "", isClosed: false, name: "", trueHdg: "", displacedThresholdM: "", displacedThresholdF: "", locationLat:0.0, locationLong: 0.0))])
airport.aptICAO = json["icao"].stringValue
airport.aptIATA = json["iata"].stringValue
airport.aptShortName = json["shortName"].stringValue
airport.aptFullName = json["fullName"].stringValue
airport.aptMunicipalName = json["municipalityName"].stringValue
airport.locationLat = json["location"]["lat"].stringValue
airport.locationLon = json["location"]["lon"].stringValue
airport.countryName = json["country"]["name"].stringValue
airport.countryCode = json["country"]["code"].stringValue
airport.continent = json["continent"]["name"].stringValue
airport.timeZone = json["timeZone"].stringValue
airport.linkLiveATC = json["urls"]["liveAtc"].stringValue
airport.linkLinkFlightRadar = json["urls"]["flightRadar"].stringValue
airport.airportWebsite = json["urls"]["webSite"].stringValue
airport.currentTimeUTC = json["currentTime"]["utcTime"].stringValue
airport.currentTimeLocal = json["currentTime"]["localTime"].stringValue
self.runwayRequest(airportICAO: icaoCode) { (vettoreRunwayModel) in
airport.runway = vettoreRunwayModel
}
DispatchQueue.main.async { // ERROR LOOKS HERE..
self.airportVector.append(airport) // aggiungo ad airport vector l'aeroporto trovato
closure()
}
case.failure(let error) :
debugPrint(error)
debugPrint("cazzoo")
}
}
}
}
}
ошибка смотрит на self.airportVector.append, потому что это @Published var и я не знаю, как решить проблему ..
спасибо за помощь,