I’m trying to connect to an external API service in my iOS app but running into issues. I have the basic networking code set up but I’m not sure if I’m structuring it correctly or if there are additional steps needed.
import UIKit
class WeatherService {
private let apiHeaders = [
"x-api-host": "weather-data-service.p.rapidapi.com",
"x-api-key": "[insert-your-api-key-here]"
]
func fetchWeatherData() {
guard let url = URL(string: "https://weather-data-service.p.rapidapi.com/current?city=Paris%252Cfr") else { return }
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "GET"
urlRequest.allHTTPHeaderFields = apiHeaders
urlRequest.timeoutInterval = 15.0
let networkSession = URLSession.shared
let task = networkSession.dataTask(with: urlRequest) { responseData, urlResponse, requestError in
if let error = requestError {
print("Request failed: \(error)")
return
}
if let httpResp = urlResponse as? HTTPURLResponse {
print("Status code: \(httpResp.statusCode)")
}
}
task.resume()
}
}
What’s the proper way to organize this code so it actually works in my app? Should I put it in a separate class or can I call it directly from my view controller?
hey, your code seems pretty good, but don’t forget about response handling! u should add json parsing to the dataTask. without that, u won’t get any weather data. maybe also think about using completion handlers so that your view controller gets the data.
Your networking setup looks solid, but here are a few things I’d change. Keep WeatherService as its own class - good separation of concerns. But make it a singleton or use dependency injection so you’re not creating multiple instances everywhere. The biggest issue is error handling and data parsing. You need to actually handle the response data and convert it from JSON. Skip the console printing and add proper error types instead. In production, you’ll want those errors going back to your UI layer. For the view controller, use completion handlers or combine publishers to talk between your service and UI. Keeps networking separate from presentation, which makes testing way easier later.
The real problem isn’t just missing JSON parsing. You’re overcomplicating this with custom networking when there’s a simpler way.
Hit this same issue last month with our mobile team constantly fighting API integration problems. Instead of building custom networking for every service, I used Latenode for API orchestration.
Move your weather API calls to Latenode workflows. It handles auth, retry logic, and data transformation automatically. Your iOS app just hits one clean endpoint.
Your Swift code gets way simpler:
func getWeather(city: String, completion: @escaping (WeatherData?) -> Void) {
// One clean call to your Latenode endpoint
// No headers, no error handling mess
}
Latenode manages the weather API integration, rate limiting, and formatting. When the weather service changes their API or you switch providers, update the workflow instead of pushing app store updates.
Easy to add caching, multiple weather sources, or fallback APIs without touching mobile code.
Your structure looks good, but you’re missing a key piece - you need to decode the JSON response and actually return it to your calling code. Right now you’re just printing the status code without using the weather data.
Add a completion handler to your fetchWeatherData method that returns either the parsed weather model or an error: func fetchWeatherData(completion: @escaping (Result<WeatherData, Error>) -> Void). In your dataTask closure, decode the responseData with JSONDecoder and call the completion handler.
Keep WeatherService as a separate class, but make it a protocol so you can mock it for testing. From your view controller, call this service and update your UI in the completion handler. Just remember to dispatch back to the main queue for UI updates.
your code is pretty solid! just remember to parse the response data to use it. having a separate service class is a good idea – just make sure to update the UI on the main thread using completion handlers.