I am going through a problem in my SwiftUI venture the place the UI isn’t updating routinely after fetching knowledge. I’ve a WeatherViewModel fetching climate knowledge for a number of areas, and the UI does not replicate the modifications till I manually set off an replace by urgent a button. I’ve tried utilizing @Revealed properties and ObservableObject, however the issue persists.
I tried to make use of @Revealed properties and ObservableObject in my code.Regardless of these efforts, the UI nonetheless does not replace routinely.
the climate knowledge mannequin:
import Basis
import Basis
// MARK: - Welcome
struct WeatherDataModel: Codable {
let coord: Coord
let climate: [Weather]
let base: String
let foremost: Primary
let visibility: Int
let wind: Wind
let clouds: Clouds
let dt: Int
let sys: Sys
let timezone, id: Int
let title: String
let cod: Int
}
// MARK: - Clouds
struct Clouds: Codable {
let all: Int
}
// MARK: - Coord
struct Coord: Codable {
let lon, lat: Double
}
// MARK: - Primary
struct Primary: Codable {
let temp, feelsLike, tempMin, tempMax: Double
let strain, humidity: Int
enum CodingKeys: String, CodingKey {
case temp
case feelsLike = "feels_like"
case tempMin = "temp_min"
case tempMax = "temp_max"
case strain, humidity
}
}
// MARK: - Sys
struct Sys: Codable {
let kind, id: Int
let nation: String
let dawn, sundown: Int
}
// MARK: - Climate
struct Climate: Codable {
let id: Int
let foremost, description, icon: String
}
// MARK: - Wind
struct Wind: Codable {
let velocity: Double
let deg: Int
}
class Location: ObservableObject, Identifiable {
let id = UUID()
@Revealed var title: String
@Revealed var weatherDataModel: WeatherDataModel?
init(title: String) {
self.title = title
}
}
class WeatherViewModel: ObservableObject {
@Revealed var areas: [Location] = []
func fetchWeather(for location: Location) {
// Implement API request to OpenWeatherMap utilizing URLSession
// You may want to interchange "YOUR_API_KEY" along with your precise OpenWeatherMap API key
let apiKey = "8281a792c5f995747b19a57c8e52ea8d"
let urlString = "https://api.openweathermap.org/knowledge/2.5/climate?q=(location.title)&appid=(apiKey)"
// let urlString = "https://api.openweathermap.org/knowledge/2.5/climate?q=mexico&appid=(apiKey)"
guard let url = URL(string: urlString) else { return }
URLSession.shared.dataTask(with: url) { knowledge, _, error in
guard let knowledge = knowledge, error == nil else {
return }
do {
let decodedData = attempt JSONDecoder().decode(WeatherDataModel.self, from: knowledge)
DispatchQueue.foremost.async {
location.weatherDataModel = decodedData
print("Climate knowledge fetched efficiently: (decodedData)")
}
} catch {
print("Error decoding climate knowledge: (error)")
}
}.resume()
}
}
Additionally for some unusual purpose the view does replace routinely with the .onAppear however then after I click on the button which clearly has no code in it then the view updates and the info from the API is displayed.
the view receiving the info:
//
// TestView.swift
// Amun
//
// Created by Richard Nkanga on 09/02/2024.
//
import SwiftUI
struct HomeView: View {
@StateObject personal var viewModel = WeatherViewModel()
@State var names = ["UNITED STATES", "Montreal", "Nigeria", "poland", "London"]
@State personal var newLocation = "Canada"
@State personal var isEditing = false
var physique: some View {
NavigationStack {
ZStack {
Coloration(.background)
.ignoresSafeArea(.all)
.onAppear {
}
VStack {
Checklist(viewModel.areas, id: .id) { locs in
HStack {
Textual content(locs.title)
Textual content("(Double(locs.weatherDataModel?.foremost.temp ?? 0))")
Spacer()
if let weatherData = locs.weatherDataModel {
Textual content("Temp: (Int(weatherData.foremost.temp))°C")
Textual content("Temp: (weatherData.title)")
} else {
Textual content("Loading...")
}
}
}
.onAppear {
for title in names {
let location = Location(title: title)
viewModel.areas.append(location)
viewModel.fetchWeather(for: location)
}
}
Button(motion: {
isEditing.toggle()
}, label: {
Textual content(isEditing ? "Carried out" : "Edit")
.foregroundColor(Coloration.purple)
})
}
}
.background(Coloration.purple)
.navigationTitle("Climate")
}
}
}
#Preview {
HomeView()
}
The ui by no means updates and simply retains displaying loading…