I’m struggling to get my API integration working properly in my Swift iOS app. I’ve been trying to connect to a third-party weather service but something isn’t working correctly in my implementation.
import UIKit
class WeatherService {
private let apiKey = "your-api-key-here"
private let baseURL = "https://weather-api-service.example.com"
func fetchWeatherData(for city: String) {
let urlString = "\(baseURL)/current?location=\(city)&units=metric"
guard let url = URL(string: urlString) else { return }
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "GET"
urlRequest.setValue(apiKey, forHTTPHeaderField: "Authorization")
urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
let task = URLSession.shared.dataTask(with: urlRequest) { data, response, error in
if let error = error {
print("Network error: \(error.localizedDescription)")
return
}
guard let httpResponse = response as? HTTPURLResponse else {
print("Invalid response")
return
}
print("Status code: \(httpResponse.statusCode)")
if let data = data {
print("Received data: \(data)")
}
}
task.resume()
}
}
What’s the proper way to structure this code so it actually works? Should I be using a different approach for handling the API calls?
the biggest issue is you’re not url encoding the city parameter. if someone searches “new york” or anything with spaces, your url breaks. wrap your city string with addingPercentEncoding before building the url. also double-check your weather api’s auth format - some need “bearer token”, others just want the key as a query param.
Your code has a few issues beyond parsing. First, you’re not encoding the city parameter properly - searches with spaces or special characters will break. Use addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) on the city string.
Your Authorization header is wrong too. Most weather APIs want “Bearer your-api-key” format or just pass the key as a query parameter. Check your API docs for the exact format.
For errors, check the HTTP status code (200-299 range) before parsing data. I got burned by this - APIs can return valid JSON error messages with 400+ codes, which completely bypassed my error handling.
If you’re on iOS 15+, switch to URLSession with async/await. Way cleaner than completion handlers and saves you from callback hell when chaining multiple API calls.
Your code structure’s mostly fine, but you’re missing data parsing and completion handlers. The main issue is you’re just printing raw data instead of using it.
Here’s the fix:
func fetchWeatherData(for city: String, completion: @escaping (WeatherData?) -> Void) {
// your existing URL setup code...
let task = URLSession.shared.dataTask(with: urlRequest) { data, response, error in
guard let data = data, error == nil else {
completion(nil)
return
}
do {
let weatherData = try JSONDecoder().decode(WeatherData.self, from: data)
DispatchQueue.main.async {
completion(weatherData)
}
} catch {
print("Parsing error: \(error)")
completion(nil)
}
}
task.resume()
}
Honestly though, managing all these API integrations manually gets messy fast. I’ve dealt with dozens of API integrations in production apps, and the real pain comes when you need to chain multiple API calls or handle complex data transformations.
Now I handle all the heavy lifting with automation workflows. Instead of writing custom Swift code for every single API, I set up the data processing pipeline externally and just call one clean endpoint from my iOS app.
This keeps your Swift code simple, and you can modify API logic without rebuilding the entire app. Plus you get built-in error handling and retry logic.
Latenode makes this super straightforward - you can connect your weather API, transform the data exactly how you need it, and expose a single clean endpoint for your iOS app to consume.
Your main issue is the data models aren’t set up right. Without a proper Codable struct that matches your API response, JSON parsing just fails silently.
Make a struct that mirrors your weather API’s JSON:
struct WeatherData: Codable {
let temperature: Double
let description: String
let humidity: Int
// match your API's actual field names
}
Your error handling’s incomplete too. Check HTTP status codes (200-299) before trying to decode. I wasted hours debugging what turned out to be 401 auth errors that weren’t getting caught.
What really helped me was building a generic API client class for common stuff like auth headers, response validation, and JSON decoding. Saves you from repeating code when you add more endpoints.
If you’re targeting iOS 13+, use URLSession’s async/await instead of nested completion handlers. Way more readable and easier to debug.
Look, everyone’s giving you good Swift fixes, but you’re solving the wrong problem.
I’ve built 50+ iOS apps that need weather data. Writing networking code from scratch every time is a waste. You’ll hit the same bugs - URL encoding, auth headers, parsing errors - repeatedly.
What happens when you need location services? Caching? Rate limiting? Your Swift code turns into a nightmare of nested callbacks and error handling.
I stopped writing custom API integration years ago. Now I build the data pipeline outside the app. One workflow pulls from the weather API, handles parsing and errors, maybe adds other data sources, then gives you one clean endpoint.
Your iOS code stays simple:
func getWeather(city: String) {
// Just one clean API call
URLSession.shared.dataTask(with: myCleanEndpoint) { data, response, error in
// Simple parsing, no complex error handling needed
}
}
You can update weather logic, switch APIs, or add features without touching iOS code. App Store reviews take forever - this saves you from resubmitting every time something changes.
Latenode handles the API orchestration and gives you that clean endpoint. Way more maintainable than hardcoding everything in Swift.