iosswift5urlsession

Do you need weak self in the closure of a data task?


Say you have

extension APISingleton {

    func items (
        _ blah: Blah?,
        completionOnMain: ( (_ status: Int, _ found: Blahs) -> ())? = nil
    ) {
        let t = URLSession.shared.dataTask(with: r) { [weak self] (d, r, r) in
             guard let self else { ..; return }
             blah
             self.blah
             DispatchQueue.main.async { completionOnMain?(666, []) }
             blah
             DispatchQueue.main.async { completionOnMain?(200, parsed) }

        }
        p = task.progress.etc {NB, p is held somewhere}
        t.resume()
    }

    func refunds ( ... other similar api calls
}

and you call it from anywhere, perhaps a VC, as

api.items(thisUser) { .. etc
    // note, obviously you use weak self here in the VC
    // this, obviously, is not what the question is about TY
    foldin(stuff: found)
}

I have always checked that self still exists in

URLSession.shared.dataTask(with: r) { [weak self] (d, r, r) in

However, that could be completely pointless. What is the situation?

I can't see how a retain cycle could be created since everything in the closure is only within .items within the API singleton.


Solution

  • I know that this is not a literal answer to the question, but I'd like to suggest an example how to use progress report with the async/await API

    Run the code in a Playground and replace https://example.com/pathToLargeFile.zip with a real URL pointing to a large file

    class ProgressTest : NSObject, URLSessionTaskDelegate {
        
        private var progressObservation: NSKeyValueObservation?
        
        func load() async {
            do {
                let url = URL(string: "https://example.com/pathToLargeFile.zip")!
                let (data, _ ) = try await URLSession.shared.data(from: url, delegate: self)
                print("complete")
            } catch {
                print(error)
            }
        }
        
        func urlSession(_ session: URLSession, didCreateTask task: URLSessionTask) {
            progressObservation = task.progress.observe(\.fractionCompleted) { progress, value in
                print("progress: ", progress.fractionCompleted)
            }
        }
    }
    
    
    Task {
        let test = ProgressTest()
        await test.load()
    }