Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DispatchQueue vs Delegates vs Closures in Swift

Excuse me if this a noobish question but I don't know the difference between executing a block of code after an API request is received and parsed via GCD, delegates and closures.

As far as I know, a creating a session to download data from an API URL is done on the main thread unless I execute the code inside a a GCD block or a delegate or a closure.

Here are two examples: Using GCD

DispatchQueue.global(qos: .utility).async {

        let requestURL = URL(string: "http://echo.jsontest.com/key/value/one/two")
        let session = URLSession.shared
        let task = session.dataTask(with: requestURL!) {
            (data, response, error) in

            print(data as Any)

            DispatchQueue.main.async {
                print("Hello")
            }
        }
        task.resume()
    }

Using Delegate:

import Foundation
import UIKit

protocol WeatherDataDownloaderProtocol {
    func setData(weatherData: WeatherData)
}

class WeatherDataDownloader {
var weatherData = WeatherData()
var delegate: WeatherDataDownloaderProtocol?

func downloadWeatherData() {
    let API_URL = WEATHER_FORECAST_URL
    guard let URL = URL(string: API_URL) else {
        print("Error: No valid URL")
        return
    }
    let config = URLSessionConfiguration.default
    let session = URLSession(configuration: config)

    let task = session.dataTask(with: URL) { (data, response, error) in
        guard error == nil else {
            print("Error getting data")
            print("\(error)")
            return
        }

        guard let responseData = data else {
            print("Error: Did not receive data")
            return
        }

        do {
            guard let JSON = try JSONSerialization.jsonObject(with: responseData, options: []) as? Dictionary<String, AnyObject> else {
                print("Error: Error trying to convert data to JSON")
                return
        }

            print(JSON)

            self.sendDataBack()

        } catch {
            print("Error: Parsing JSON data error")
            return
        }
    }
    task.resume()
}

    func sendDataBack() {
        if let _delegate = delegate {
            _delegate.setData(weatherData: weatherData)
        }
    }
}

Both, print("Hello") and print(JSON) + self.sendDataBack() will execute after the JSON is retrieved and parsed. What's the difference between both methods? Does it have anything to do with whether my app would crash if I navigate out of the viewController while waiting for the network response?

Thanks a lot

like image 536
Tarek Avatar asked Mar 09 '26 18:03

Tarek


1 Answers

In your first approach, the .async call is not necessary. URLSession dataTask is a background task.

So the choice is not GDC vs. delegates but completion handler vs. delegate.

Opinion based:

Using a delegate is more work and harder to read because you have to check in other areas of the code if the delegate is actually set and who it is and what it actually does.

Also no code might be executed in case the delegate does not exist any more at the time your network call has finished. So for this case I plead for using a completion closure.

like image 104
shallowThought Avatar answered Mar 12 '26 08:03

shallowThought



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!