To return data from an asynchronous call in Swift, you typically use closures, completion handlers, or async/await if you’re using Swift 5.5 or later. Here are examples of each approach:
- Using Completion Handler:
func fetchDataFromURL(_ url: URL, completion: @escaping (Result<Data, Error>) -> Void) {
URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
completion(.failure(error))
return
}
guard let data = data else {
completion(.failure(NSError(domain: "No data found", code: -1, userInfo: nil)))
return
}
completion(.success(data))
}.resume()
}
// Usage
fetchDataFromURL(someURL) { result in
switch result {
case .success(let data):
// Use the data here
case .failure(let error):
// Handle errors
}
}
Explanation:
-
fetchDataFromURL
takes a completion handler closure as an argument. - Inside the function, a URL session data task is created.
- The completion closure is called within the data task closure based on the outcome (success with data, error, or no data).
- The calling code can handle the results (data or error) within the completion handler.
- Using Closures:
func fetchDataFromURL(_ url: URL, completion: @escaping (Result<Data, Error>) -> Void) {
URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
completion(.failure(error))
return
}
guard let data = data else {
completion(.failure(NSError(domain: "No data found", code: -1, userInfo: nil)))
return
}
completion(.success(data))
}.resume()
}
// Usage
fetchData { data, error in
if let data = data {
// Handle successful data retrieval
} else if let error = error {
// Handle error
}
}
Explanation:
-
fetchDataFromURL
takes a completion handler closure as an argument. - Inside the function, a URL session data task is created.
- The completion closure is called within the data task closure based on the outcome (success with data, error, or no data).
- The calling code can handle the results (data or error) within the completion handler.
- Using Async/Await (Swift 5.5 or later):
func fetchDataFromURL(_ url: URL) async throws -> Data {
let response = try await URLSession.shared.data(from: url)
return response.data
}
// Usage
Task {
do {
let data = try await fetchDataFromURL(someURL)
// Use the data here
} catch {
// Handle errors
}
}
Explanation:
-
fetchDataFromURL
is declared as anasync
function, indicating it performs asynchronous work. - Inside the function,
try await URLSession.shared.data(from: url)
makes an asynchronous network call and waits for the response before proceeding. - The function throws any errors encountered during the call.
- The function returns the retrieved data as
Data
.
Choosing the Right Method:
- Async/Await is generally preferred for newer Swift versions (5.5 and above) due to its cleaner syntax and easier error handling.
- Completion Handler might be necessary for compatibility with older Swift versions or when dealing with multiple asynchronous calls within the same function.