iOS - First network request fails after unlock
Asked Answered
V

3

7

I have an iOS app that pulls user data from the server in applicationDidBecomeActive.

If the user presses the home button, then returns to the app, either through the app icon or multitasking screen, the function works fine.

If the user locks the device in the mean time (either while still in the app or pressing home, then locking) the network request fails. I am using Alamofire. The response object is nil and the result.data is empty. There is no request logged on the server either. The failure happens instantly.

Vandusen answered 9/3, 2016 at 20:5 Comment(0)
C
7

Apple Tech Note TN2277, says that the kernel can reclaim sockets out from under apps without them having any idea what happens. Here's the relevant part :

Testing Socket Reclaim

If you're going to write code that handles a socket's resources being reclaimed by the kernel, you have to figure out how to test it. The exact circumstances under which the system might reclaim a socket's resources are purposely not documented; this gives us the flexibility to improve things in the future. However, on current systems (iOS 4.0 through iOS 4.3), you can get the system to reclaim resources from the sockets in your app by:

  1. putting your app in the background
  2. ensuring that the app is suspended
  3. locking the screen

When your app resumes execution it will find that it's sockets have been reclaimed.

To workaround this, try to create new Alamofire.Manager whenever my AppDelegate's applicationWillEnterForeground is called. Hope this helps you..

Cavanagh answered 9/3, 2016 at 20:40 Comment(6)
but I'm not running anything in the background. This network request is made in applicationDidBecomeActive so surely at that point my app should have network access?Vandusen
My guess is that NSURLSession (which Alamofire.Manager is caching), has one or more sockets it keeps open (possibly to avoid renegotiating TLS handshakes). Then, when the device is locked, the OS reclaims these sockets. The next request on them results in an EBADF errno from the system call, which gets translated into an NSError with localized description "connection closed".Cavanagh
Any idea how I can get around this? I've tried to find some sort of refresh function. The only thing I'm thinking now is having the request retryVandusen
I am having the same issue as well, any ideas? `Alamofire.Manager() doesn't workTrihedron
A solution is to use a new manager each time the app comes form the background, it worked for meViolone
Socket reclaim is more aggressive in iOS 11.4 and 12. It triggers when your app is suspended. github.com/AFNetworking/AFNetworking/issues/…Kidwell
B
2

In applicationWillEnterForeground of AppDelegate initialize your Network Manager class again, and it will solve the problem. The reason for this issue is, when you lock your device, the OS locks the sockets and does not release it when the phone is unlocked. So please again initialize your network manager class and it will solve the problem.

     func applicationWillEnterForeground(_ application: UIApplication) {
            WebServiceManager.sharedInstance.sessionManr = Alamofire.SessionManager.default
            WebServiceManager.sharedInstance.sessionManr.session.configuration.requestCachePolicy = .reloadIgnoringLocalAndRemoteCacheData

            WebServiceManager.sharedInstance.sessionManr.session.configuration.urlCache = nil
            WebServiceManager.sharedInstance.sessionManr.session.configuration.timeoutIntervalForRequest =  180 //40
            WebServiceManager.sharedInstance.sessionManr.session.configuration.httpShouldSetCookies = true
     }
Baksheesh answered 11/6, 2019 at 12:50 Comment(0)
A
0

I had a similar problem even when not using Almofire. I was sometimes getting error -1005 NSURLErrorNetworkConnectionLost (some users -1001 NSURLErrorTimedOut) from the first request after unlock.

In the logs I could see:

[connection] nw_read_request_report [C1] Receive failed with error "Software caused connection abort"

For me the solution was to wait until the application was active (applicationDidBecomeActive notification). I was starting the request from a Timer, but timers do not run in background and suspended timers are fired very soon after the application becomes running again, even before willEnterForeground notification.

After postponing my network calls I could still see the following errors in logs:

[connection] nw_flow_add_write_request [C1 A.B.C.D:443 failed parent-flow (satisfied (Path is satisfied), interface: en0[802.11], ipv4, dns)] cannot accept write requests
[connection] nw_write_request_report [C1] Send failed with error "Socket is not connected"

However those didn't break my code.

Ayana answered 27/8, 2023 at 11:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.