iOS background request timeout or network error

Device: iOS11.1 iPhoneX device and iOS11.2.5 iPhone7 devices.



What is my problem:

My application use afnetworking library to send request and get latest information from server.

It work well when app is foreground.

When the application is in background, I use silent push to awake my app and send the same request to server to get the latest information.

I have received silent push and application is awaked, but when I send the request, I cannot receive any response.

After I raise application to foreground, I can get response and it tell me the error is -1001(timeout), sometime, the error is -1005(network access error)



It seems like on iOS11, the background request is not work.

anybody tell me what is the problem?

is it any method to solve this problem?



----my request----

I am using AFHTTPSessionManager's POST method to send request.



----AFHTTPSessionManager's Interface----

- (NSURLSessionDataTask *)POST:(NSString *)URLString

parameters:(id)parameters

constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block

progress:(nullable void (^)(NSProgress * _Nonnull))uploadProgress

success:(void (^)(NSURLSessionDataTask *task, id responseObject))success

failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure



----initialize----

configuration = [NSURLSessionConfiguration defaultSessionConfiguration];


the background request have worked well on iOS9 and iOS10 devices.

What type app? Does it use location services, or VOIP, or...?

It’s likely that your app was suspended while the network operation was in progress. You have a couple of options here:

  • You can use a UIApplication background task to prevent your app being suspended while the networking operation is in progress (A)

  • You can run the request in a background session, which will resume (or relaunch) your app when the request is complete (B)

There’s a strict limit on how much UIApplication background task execution time you can get, so if the request is large then you have to do B. If the request is small, you can do either A or B, or possibly a hybrid of both.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hi, eskimo

Thank you very much for your response.


Could you please give me more information about this?

1. Why my application is work well on iOS9 and iOS10 device and can not work well on iOS 11 device? do you know what changed since iOS 11?

2. Let me descript my situation more detail.


-The trigger of my background request is silent push, when received silent push, app is in background (not be killed). <--I can received it now

I mean my task is not start when app is in foreground.

-My background task is not upload file or downlond big file, just post http request to server and wait the response to update local variable.

-I used AFNetworking Library 3.2.0, and I think AFNetworking Library used URLSession.

-After send request, I can not get the response, the completion block is not called.


These are my situation, and do you think I should try your Solution A or Solution B, or do you have Solution C now?

Why my application is work well on iOS9 and iOS10 device and can not work well on iOS 11 device? do you know what changed since iOS 11?

I’m not aware of any specific change that would cause this to behave differently on iOS 11 versus earlier systems.

My background task is not upload file or downlond big file, just post http request to server and wait the response to update local variable.

If this is a small request that you expect to complete quickly, you should use approach A.

IMPORTANT You must have an expiry handler in that case. If the request doesn’t complete in the background time you have available, your expiry handler will run and you then have to decide what to do. For example:

  • You could retry the request in a background session.

  • You could note, in persistent storage, that the request failed and that you need to retry it at some point in the future.

Regardless, your expiry handler must end the UIApplication background task because failing to do so will get your app killed by the watchdog.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hi, eskimo


Appreciate your suggestion.

Yes, my case is a small request so I tried Approach A.


This is my source code and it works well now.


__block UIApplication *app = UIApplication.sharedApplication;

_bgTask = [app beginBackgroundTaskWithExpirationHandler:^{

dispatch_async(dispatch_get_main_queue(), ^{

if (_bgTask != UIBackgroundTaskInvalid) {

[app endBackgroundTask:_bgTask];

_bgTask = UIBackgroundTaskInvalid;

}

});

}];

[self doMyBackgroundTaskWithResponseBlock:^{

if (_bgTask != UIBackgroundTaskInvalid) {

[app endBackgroundTask:_bgTask];

_bgTask = UIBackgroundTaskInvalid;

}

}];

iOS background request timeout or network error
 
 
Q