0

Call made like this

let jsonData = try JSONSerialization.data(withJSONObject: requestBody)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = jsonData

let (data, response) = try await URLSession.shared.data(for: request)

When I call it from the simulator it works perfect 100% of the time.

When I run it on the phone while on WiFi it works perfect 100% of the time.

BUT when I run it on the phone on cell network. It fails randomly.

But if I try to call that end point using another API test app on the phone. It works.

The error I get back when it fails as follows:

Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." UserInfo={_kCFStreamErrorCodeKey=57, NSUnderlyingError=0x28198df50 {Error Domain=kCFErrorDomainCFNetwork Code=-1005 "(null)" UserInfo={NSErrorPeerAddressKey=<CFData 0x2833f6e20 [0x1e1c79d10]>{length = 28, capacity = 28, bytes = 0x1c1e01bb000000002606470000200000 ... 681a00aa00000000}, _kCFStreamErrorCodeKey=57, _kCFStreamErrorDomainKey=1}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask .<2>, _NSURLErrorRelatedURLSessionTaskErrorKey=( "LocalDataTask .<2>" ), NSLocalizedDescription=The network connection was lost., NSErrorFailingURLStringKey=https://blahblah/v1/run, NSErrorFailingURLKey=https://blahblah/v1/run, _kCFStreamErrorDomainKey=1}

HangarRash
  • 7,314
  • 5
  • 5
  • 32
erotsppa
  • 14,248
  • 33
  • 123
  • 181
  • 2
    The error seems to say exactly what it means: the connection was lost. Cell networks are not as reliable as WiFi networks, so that's not surprising. Is there a reason you're surprised? Does the other test app deal with errors in a way that you don't? What coded difference is there? Without more details of the exact API call and how the server and the test app are implemented, it's not clear how we can help. – Rob Napier Mar 01 '23 at 20:12
  • Also, if this is in a playground, IIRC networking may not always work as expected in that environment. – dgatwood Apr 04 '23 at 23:33
  • Set your computer to use the internet via the GSM network of your iPhone, and then check if your app can make calls from the simulator. Are you getting any errors? – Blazej SLEBODA Apr 11 '23 at 00:32

1 Answers1

0

How large is your POST body? Cellular networking can be quite flaky at times, and losing a connection when uploading large files is not uncommon.

If you're uploading big chunks of data, a good strategy is to change the server side to allow you to upload the data in chunks, retrying each chunk until it succeeds, then combine the chunks on the server side after you finish uploading everything.

Otherwise, the next question you should ask is whether you can make the request idempotent. If it is possible to make the request in such a way that sending it twice won't cause any harm, then you should be using a GET request so that the NSURLSession machinery can retry the request after certain types of network failures, network changes, etc. POST requests are never retried.

The third thing you should ask is whether you are overriding any of the session's behavior using callbacks. If so, are you certain that you are calling the provided callback every time? Some common mistakes I've seen include:

  • Failing to call default handling for certificate/password/authentication requests that are of types that you don't care about.
  • Making NSURLConnection-style calls that continue a request instead of calling the callback (which will sometimes, but not always work).
  • Storing the callback to call after doing somsething else, and then sometimes failing to call it.
  • Calling the callback from a different dispatch queue than the one it was called on (this may be okay, but IIRC it used to cause problems).
  • Configuring the session to use a concurrent NSOperation queue.
  • Blocking/deadlocking the queue used by the session to dispatch callbacks.

and so on. Any of these things can result in very strange behavior.

Beyond that, look for any differences in the way you're setting up the session and connection between the app that works and the app that doesn't — differences in the session configuration, differences in shared cache configuration, differences in task creation, differences in threading model, etc.

Good luck.

dgatwood
  • 10,129
  • 1
  • 28
  • 49