2

Can anyone tell me how to use the Alamofire background service correctly?

My attempts are:

Login View Controller

// Create a global variable for the manager
var manager = Alamofire.Manager()
var configuration = NSURLSessionConfiguration()


class LoginViewController: UIViewController {

    // set the configuration for the manager
          configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier("com.xxx.app.backgroundService")
          configuration.sharedContainerIdentifier = "com.xxx.app.backgroundService"
}

Now creating my login attempt, when successful go to the MainViewController and do here some more Requests.

 manager.request(.POST, "\(serviceUrl)public/service/authenticate", parameters: ["email": txtEmail.text!, "password": txtPassword.text!]) {
   ......
}

Here ill get my token for all requests, so ill add the to my global configuration:

class MainViewController: UIViewController {
     if let token: AnyObject = NSUserDefaults.standardUserDefaults().objectForKey("token") {
        configuration.HTTPAdditionalHeaders = ["Authorization": "Bearer \(token)"]
        manager = Alamofire.Manager(configuration: configuration)
    }
}

But now when ill logout and login again - ill get the following errors:

Warning: A background URLSession with identifier xxx.xxx.app.backgroundService already exists!

And the app crashes with:

*** Terminating app due to uncaught exception 'NSGenericException', reason: 'Task created in a session that has been invalidated'
*** First throw call stack:

So i really dont know how do use the background-service to get the following result:

At login attempt, i dont need to add an authentication header. But then, i would like to add it to every request. All requests should run as background service.

Can anyone help me out, how to solve that in a correct way? Thanks in advance!

derdida
  • 14,784
  • 16
  • 90
  • 139

1 Answers1

6

You have multiple problems. The first is that you need to pass the configuration object into the Manager initializer. Otherwise you are not using the configuration for the underlying URL session in the Manager instance.

The second issue is that you should NOT set header values on a configuration after it has been applied to a Manager instance. The Apple docs specifically call this out. We also call this out in our README. If you need to deal with authorization tokens, you need to pass them as a header attached to the actual request.


Update #1

Here's a small example showing how you could create a Manager instance that could be used globally.

class NetworkManager {
    var authToken = "1234" // You'll need to update this as necessary

    let manager: Manager = {
        let configuration: NSURLSessionConfiguration = {
            let identifier = "com.company.app.background-session"
            let configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier(identifier)
            return configuration
        }()

        return Manager(configuration: configuration)
    }()

    static let sharedInstance = NetworkManager()
}

class ExampleClass {
    func startNetworkRequest() {
        let headers = ["Authorization": NetworkManager.sharedInstance.authToken]

        NetworkManager.sharedInstance.manager.request(.GET, "https://httpbin.org/get", headers: headers)
            .responseJSON { response in
                debugPrint(response)
            }
    }
}

You'll still need to work out how to update the authToken when it expires, but this shows one way how you could use your manager instance throughout your codebase.

cnoon
  • 16,575
  • 7
  • 58
  • 66
  • Thanks for your answer! Can u give me some more information? - Where should i init the Manager variable, is that a global variable (outside a class?) - Or should i make the configuration outside any class, to make in global? It the Readme there is an information that i should attach my token to the global configuration, so it gets pushed to every request. So to help me out it would be great to have a short example where i should create my configuration, where i should set my background identifier, and where i should update my configuration (in every class where i would like to use alamofire?) – derdida Nov 06 '15 at 16:29
  • There is NOT information in the README that you should attach tokens to every request using your configuration. It explicitly points out NOT to do that. – cnoon Nov 07 '15 at 17:11
  • What did that mean then: "For HTTP headers that do not change, it is recommended to set them on the NSURLSessionConfiguration so they are automatically applied to any NSURLSessionTask created by the underlying NSURLSession." ? – derdida Nov 07 '15 at 17:22
  • You token will change over time. Therefore, it should not be attached to the configuration. – cnoon Nov 08 '15 at 19:23
  • @cnoon what is the way to revalidate the session ? like if u invalidateAndCancel() the shared session and try to request again u wont be able to that why is that so ? – MQ. Aug 25 '16 at 02:47
  • After a session has been invalidated, you no longer can execute requests on it. You MUST make a new one. – cnoon Aug 31 '16 at 14:18