iosafnetworkingafnetworking-2ios12afhttprequestoperation

AFNetworking error 53 during attempted background fetch


While updating my application to support Background App Refresh I ran into problem with AFNetworking.

I am getting NSPOSIXErrorDomain Code=53 "Software caused connection abort". The problem seems to occur in iOS 12, where the background connection gets terminated.

AFNetworking 2.6.3 is used to make the fetch.

AppDelegate.m:

- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    [OrdersService performFetch];
    completionHandler(UIBackgroundFetchResultNewData);
}

OrdersService.m:

-(void) performFetch {
    [[AFHTTPRequestOperationManager new] GET:@"https://www.example.com/orders"
        parameters:nil
           success:^(AFHTTPRequestOperation *operation, id responseObject) {

           }
           failure:^(AFHTTPRequestOperation *operation, NSError *error) {

           }
    ];
}

Console output:

[Error] GET '(null)' (0) [31.9163 s]: Error Domain=NSPOSIXErrorDomain Code=53 "Software caused connection abort" UserInfo={NSErrorFailingURLStringKey=https://www.example.com/orders, _kCFStreamErrorDomainKey=1, NSErrorPeerAddressKey={length = 16, capacity = 16, bytes = 0x100201bb3e80187c0000000000000000}, _kCFStreamErrorCodeKey=53, NSErrorFailingURLKey=https://www.example.com/orders}


Solution

  • Starting the fetch as background task with 0.1 sec delay solved the problem:

    -(void) performFetch {
        __block UIBackgroundTaskIdentifier bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"GET /orders" expirationHandler:^{
            // EXPIRED
            [[UIApplication sharedApplication] endBackgroundTask:bgTask];
            bgTask = UIBackgroundTaskInvalid;
        }];
    
        // Start the long-running task and return immediately.
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    
            // Do the work associated with the task, preferably in chunks.
            [[AFHTTPRequestOperationManager new] GET:@"https://www.example.com/orders"
                            parameters:nil
                               success:^(AFHTTPRequestOperation *operation, id responseObject) {
                                   // SUCCESS
                                   [[UIApplication sharedApplication] endBackgroundTask:bgTask];
                                   bgTask = UIBackgroundTaskInvalid;
                               }
                               failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                   // FAILURE
                                   [[UIApplication sharedApplication] endBackgroundTask:bgTask];
                                   bgTask = UIBackgroundTaskInvalid;
                               }
            ];
        });
    }