In the world of mobile app development, handling API responses and errors effectively is crucial for delivering a seamless user experience. APIs (Application Programming Interfaces) allow mobile applications to communicate with servers and retrieve data. However, issues can arise during this communication, leading to errors or unexpected responses. This guide provides three practical examples of handling API responses and errors in mobile apps.
In a mobile weather application, you want to show the current weather conditions based on user location. The app makes a request to a weather API and receives a JSON response. Here’s how to handle the response and any potential errors:
When the API call is successful, the app parses the JSON data to extract relevant weather information. If the API call fails, the app displays an error message to the user. Using a try-catch block can help manage errors effectively.
let url = URL(string: "https://api.weatherapi.com/v1/current.json?key=YOUR_API_KEY&q=London")
URLSession.shared.dataTask(with: url!) { (data, response, error) in
if let error = error {
// Handle error
DispatchQueue.main.async {
self.showErrorAlert(message: error.localizedDescription)
}
return
}
guard let data = data else { return }
do {
let weatherResponse = try JSONDecoder().decode(WeatherResponse.self, from: data)
DispatchQueue.main.async {
self.updateUI(with: weatherResponse)
}
} catch {
DispatchQueue.main.async {
self.showErrorAlert(message: "Failed to parse weather data.")
}
}
}.resume()
In a mobile to-do list application, users can create and delete tasks using a RESTful API. It’s important to handle both successful responses and various error scenarios effectively. This ensures users receive feedback on their actions.
When a user attempts to delete a task, the app sends a DELETE request to the API. If the response indicates success, the task is removed from the local list. If an error occurs (e.g., task not found, server error), the app displays a corresponding message.
const deleteTask = async (taskId) => {
try {
const response = await fetch(`https://api.todoapp.com/tasks/${taskId}`, {
method: 'DELETE',
});
if (response.ok) {
// Task deleted successfully
updateTaskList();
} else if (response.status === 404) {
alert('Task not found.');
} else {
alert('Failed to delete task. Please try again.');
}
} catch (error) {
alert('Network error: ' + error.message);
}
};
In a social media application, users can post updates and retrieve feeds using an external API. It’s essential to handle API rate limiting to avoid disruptions in service. When the rate limit is exceeded, the server returns a specific error code.
In this example, the app checks for a rate limit error and informs the user about the wait time before they can make another request. By implementing exponential backoff, the app can retry requests after a delay.
import requests
import time
def post_update(update):
try:
response = requests.post('https://api.socialmedia.com/posts', json={'update': update})
response.raise_for_status()
except requests.exceptions.HTTPError as err:
# Handle rate limit error
if response.status_code == 429:
wait_time = int(response.headers['Retry-After'])
print(f'Rate limit exceeded. Please wait {wait_time} seconds.')
time.sleep(wait_time)
post_update(update) # Retry after waiting
else:
print('Failed to post update:', err)
else:
print('Update posted successfully!')
By employing these examples of handling API responses and errors in mobile apps, developers can create more resilient applications that provide users with a better experience, even when things go wrong.