尝试后台获取期间出现 AFNetworking 错误 53

AFNetworking error 53 during attempted background fetch

在更新我的应用程序以支持后台应用程序刷新时,我 运行 遇到了 AFNetworking 问题。

我得到 NSPOSIXErrorDomain Code=53 "Software caused connection abort"。问题似乎出现在 iOS 12 中,后台连接被终止。

AFNetworking 2.6.3 用于进行抓取。

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) {

           }
    ];
}

控制台输出:

[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}

将提取作为后台任务以 0.1 秒的延迟启动解决了问题:

-(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;
                           }
        ];
    });
}

下面链接的一些解决方案有助于解决 Lower protocol stack error: 53

AFNetworking GitHub 上的信息线程,包含相关详细信息和背景信息:AFNetworking issue

请务必阅读最后的评论以获取有见地的详细信息:

In terms of workarounds, there’s three things you can do here, and it may make sense to do all three, or some subset, depending on the requirements of your real app. To wit:

A. If you regularly bounce in and out of your app — for example, you bounce the user out to Safari so that they can do some authentication task and then you want Safari to bounce the user back to your app — it might make sense to use a UIApplication background task to prevent your app from being suspended during those bounces.

This approach will only keep your app running for a few minutes, but if that’s sufficient for common user scenarios then it’s worthwhile doing.

B. You can retry requests yourself. Even if you weren’t running into this problem this is generally a good idea. There’s a vast array of transient issues that can cause requests to fail, and a single retry will often get you past the error without further remedial work.

The obvious gotcha here is idempotency. You can retry idempotent requests without any worries, but you’ll need some cunning app-specific logic if you want to retry non-idempotent requests.

C. You can invalidate your session when you go into the background and then re-create the session when you come back into the foreground. The new session will not share any connections with the old one, so this problem just can’t occur.

As I mentioned earlier, combining approaches might make sense. For example, A and C work together well, allowing you to avoid the cost of session invalidation unless you run out of background execution time. And you might want to do B because it has benefits outside of this problem space.

就我而言,它发生在 iOS12.3 设备上

2019-08-05 17:38:50.988880-0700 myApp[2988:1589883] [BoringSSL] nw_protocol_boringssl_error(1584) [C15.1:4][0x10dd6e700] Lower protocol stack error: 53
2019-08-05 17:38:50.990132-0700 myApp[2988:1589883] TIC Read Status [15:0x281d59d40]: 1:53
2019-08-05 17:38:50.995585-0700 myApp[2988:1589883] Task <D62956CC-6C2B-4D5E-B1DA-0A5CA2BB60EF>.<1> HTTP load failed (error code: 53 [1:53])
2019-08-05 17:38:51.000334-0700 myApp[2988:1588479] Task <D62956CC-6C2B-4D5E-B1DA-0A5CA2BB60EF>.<1> finished with error - code: 53

正在让您的应用在后台模式下 运行:Apple's doc: How to do background fetch

此外,有关后台任务的良好信息来源:apple dev forum