Apollo-ios: HTTPNetworkTransport still using completion handler blocks

Created on 22 Aug 2019  Â·  21Comments  Â·  Source: apollographql/apollo-ios

The latest release (0.15.0) introduced the ability to use a URLSession instead of a URLSessionConfiguration, this allows using a background session on the HTTPNetworkTransport.

However, HTTPNetworkTransport is still using completion handler blocks, which are not supported in a background session, instead of using a delegate for that.

Do you have any plans to change this behavior so HTTPNetworkTransport is always using a delegate instead of completion handler blocks?

bug networking-stack question

Most helpful comment

👋 any update on this?

All 21 comments

Remind me why a completion handler can't be used in a background session? I thought when you got the background wakeup call you got a completion block to fire when your action had completed.

I thought it too, but when I'm getting the following crash when fetching the query.

2019-08-24 10:05:34.535996+0200 BlahBlah[60902:3911842] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Completion handler blocks are not supported in background sessions. Use a delegate instead.'
*** First throw call stack:
(
    0   CoreFoundation                      0x0000000110cac8db __exceptionPreprocess + 331
    1   libobjc.A.dylib                     0x000000011024fac5 objc_exception_throw + 48
    2   CFNetwork                           0x00000001135c179d -[__NSURLBackgroundSession validateSerializabilityForRequest:completion:] + 172
    3   CFNetwork                           0x00000001135c1f01 -[__NSURLBackgroundSession _onqueue_dataTaskForRequest:completion:] + 43
    4   CFNetwork                           0x00000001135c1e20 __58-[__NSURLBackgroundSession dataTaskForRequest:completion:]_block_invoke + 34
    5   CFNetwork                           0x00000001135c1bf0 __68-[__NSURLBackgroundSession performBlockOnQueueAndRethrowExceptions:]_block_invoke + 64
    6   libdispatch.dylib                   0x0000000112bbedb5 _dispatch_client_callout + 8
    7   libdispatch.dylib                   0x0000000112bccd08 _dispatch_lane_barrier_sync_invoke_and_complete + 132
    8   CFNetwork                           0x00000001135c1b58 -[__NSURLBackgroundSession performBlockOnQueueAndRethrowExceptions:] + 161
    9   CFNetwork                           0x00000001135c1d8d -[__NSURLBackgroundSession dataTaskForRequest:completion:] + 206
    10  Apollo                              0x0000000111ec71e2 lprofRestoreSigKill + 1154
    11  Apollo                              0x0000000111ec7fb1 lprofRestoreSigKill + 4689
    12  Apollo                              0x0000000111ec8a30 lprofRestoreSigKill + 7376
    13  Apollo                              0x0000000111f290ac block_copy_helper.94 + 7916

The reason I would say is that the completion handler blocks may have been deallocated while the app is in background

Blargh. Will take a look when I get back.

👋 any update on this?

Not at the moment - I think we're probably going to have to add some additional protocol methods to make this work correctly, and I'm in the middle of about 14 other things. Would be more than happy to look at a pull request if you've got more time!

This is very important, as Apple is going to reject apps that have a Share extension that starts uploads configured without a background session.

@kroussevrb Thanks for the heads up - again, I'm swamped with a couple other things but would be more than happy to look at a PR if you have some time!

TWIMC, I've just released ApolloAlamofire 0.6.0, which is updated for Apollo 0.19.0 and allows using an Alamofire delegate for the Apollo transport.

This is great, now the only thing missing is a pure Apollo solution for those of us who can't afford to import Alamofire as a dependency. I am aware of the suggestion to submit a PR for that but I don't know if I will be able to get around to it (or even if I do, not sure it will be the best solution as I am not familiar with Apollo's source code)

Any update on this functionality? :)

Gonna be a bit - I've been doing some exploration around this and some other restructuring of the networking stack for HTTP recently, but I need to get it more stable before I write up a CFP.

@designatednerd Right on! Thanks so much for the quick reply. Love this SDK and everything about Apollo!

I rewrote the network transport to be able to handle this but my implementation is very specific to our project, so can't help out here.

Hi folks, I finally got something that will work with a background session functional. Please check out #1163, I would love your feedback.

This has (finally) shipped with 0.27.0. Thanks to all for your patience!

Hey Can anyone please share the right way of configuring apollo for the background task to work. earlier i was using 0.21.0 for all foreground tasks and now updated to 0.27.0 so as to hit api from background.
Any example would be helpful. I just want to know what all needs to be done for the background to work.

Hi! You can pass the background session configuration you receive from the system into a URLSessionClient, since that takes a session configuration. Then, you pass that client into the initializer for HTTPNetworkTransport.

Does that help?

You also have to implement the background session delegates to handle download progress and response.
On 30. Jul 2020, 17:21 +0200, Ellen Shapiro notifications@github.com, wrote:

Hi! You can pass the background session configuration you receive from the system into a URLSessionClient, since that takes a session configuration. Then, you pass that client into the initializer for HTTPNetworkTransport.
Does that help?
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or unsubscribe.

@diegoventura are you talking about the delegates on UIApplication? We cover a lot of delegate methods in URLSessionClient

  import Foundation
  import Apollo

  // MARK: - Singleton Wrapper

 class Network {

static var cachedShared: Network?

static var shared: Network {
    guard cachedShared == nil else {
        return cachedShared!
    }

    cachedShared = Network()
    return cachedShared!
}

static func resetShared() {
    cachedShared = nil
}

var networkTransport: HTTPNetworkTransport {
    let configuration = URLSessionConfiguration.default
        configuration.httpAdditionalHeaders = [
            "Custom-Authorization": "Bearer \(AuthenticationToken.current?.token ?? "")",
            "IS-MOBILE-APP": "true"
        ]
    let url = URL(string: Constant.urlString)!
    let client = URLSessionClient(sessionConfiguration: configuration)
    return HTTPNetworkTransport(url: url, client: client)
}

// Use the configured network transport in your Apollo client.
private(set) lazy var apollo = ApolloClient(networkTransport: self.networkTransport)
 }

This is code I am using to instantiate apollo client.
@designatednerd how did we get background session from system ?

Here's all of Apple's documentation about how to get a background session. You'll probably want to make your networkTransport var a function that takes the URLSessionConfiguration as a parameter.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Robuske picture Robuske  Â·  3Comments

designatednerd picture designatednerd  Â·  3Comments

jeromeDms picture jeromeDms  Â·  5Comments

hiteshborse12 picture hiteshborse12  Â·  4Comments

MrAlek picture MrAlek  Â·  3Comments