?查資料一天杭措,埋坑半天,寫文章兩小時钾恢,讀5分鐘手素。 我在坑外鸳址,等著你會來?
現(xiàn)象
系統(tǒng)版本:iOS12
build configuration: Release
場景: 后臺收到Push進(jìn)入前臺,觸發(fā)網(wǎng)絡(luò)請求泉懦。
Xcode 輸出:
nw_socket_handle_socket_event [C58:1] Socket SO_ERROR [9: Bad file descriptor]
nw_socket_get_input_frames [C58:1] recvmsg(fd 33, 1024 bytes) [57: Socket is not connected]
[BoringSSL] nw_protocol_boringssl_error(1584) C49.1:2 Lower protocol stack error: 53
load failed with error Error Domain=NSPOSIXErrorDomain Code=53 "Software caused connection abort"
分析
BoringSSL稿黍,可能與ssl有關(guān)
nw_protocol_boringssl_error(1584)
nw_protocol_boringssl_error(1584)
結(jié)論為: 可能與App Transport Security Settings下的Allow Arbitrary Loads有關(guān)
Bad file descriptor, 應(yīng)該是socket斷開崩哩,使用了無效的句柄
iOS listen socket become bad file descriptor after screen lock
[[iOS 12 Beta 11] NSPOSIXErrorDomain Code=53: Software caused connection abort](https://github.com/AFNetworking/AFNetworking/issues/4279)
結(jié)論為:
正常情況下app進(jìn)入后臺(鎖屏或切app)后巡球,斷開了網(wǎng)絡(luò)連接,app重新進(jìn)入前臺時邓嘹,socket有可能超時酣栈,斷開無效。
但 此次在iOS12下的bug在于: applicationWillEnterForeground及applicationDidBecomeActive之間新發(fā)起的請求汹押,使用了失效的socket句柄矿筝。不知道是否為AFNetwork和Alamofire底層復(fù)用問題,還是NSURLSession的問題鲸阻。
方案
經(jīng)和@原鳴清溝通跋涣,發(fā)現(xiàn)我們的情況和他所遇到的情況并不相同,更接近于第2種判斷鸟悴,即socket句柄無效
1. 延時發(fā)起網(wǎng)絡(luò)請求陈辱,延至applicationDidBecomeActive之后處理。
2. 向系統(tǒng)要求后臺任務(wù)權(quán)限细诸。
3. 重新創(chuàng)建網(wǎng)絡(luò)相關(guān)對象沛贪,拋棄原有網(wǎng)絡(luò)對象。
個人為了快速fix bug采用了延時方案震贵。在收到applicationDidBecomeActive消息通知后利赋,延時0.0秒,處理網(wǎng)絡(luò)請求及后臺Push事件猩系。但建議有心人媚送,看是否可以通過AFNetworking獲得鏈接狀態(tài)等,采取處理寇甸。將bug fix在網(wǎng)絡(luò)底層塘偎。
后續(xù)
經(jīng)過測試發(fā)現(xiàn)
//iOS11.4.1
<Debug> 2018/11/30 16:06:46 AppDelegate -[AppDelegate applicationWillEnterForeground:] XX: apns push:
<Debug> 2018/11/30 16:06:46 APNSManager -[APNSManager userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:] XX: apns push
<Debug> 2018/11/30 16:06:46 AppDelegate -[AppDelegate applicationDidBecomeActive:] XX: apns push:
?
//iOS12.1
<Debug> 2018/11/30 16:13:25 AppDelegate -[AppDelegate applicationWillEnterForeground:] XX: apns push:
2018/11/30 16:13:25 APNSManager -[APNSManager userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:] XX: apns push?
<Debug> 2018/11/30 16:13:25 AppDelegate -[AppDelegate applicationDidBecomeActive:] XX: apns push:
<Debug> 2018/11/30 16:13:25 AppDelegate -[AppDelegate applicationWillResignActive:] XX: apns push:
<Debug> 2018/11/30 16:13:26 AppDelegate -[AppDelegate applicationDidBecomeActive:] XX: apns push:
?
iOS12.1在鎖屏后,會多調(diào)用一次applicationWillResignActive拿霉。
Final
在applicationWillResignActive中使用beginBackgroundTaskWithName:expirationHandler:開啟一個task比較nice
__block UIBackgroundTaskIdentifier bgTask? =
?????????[[UIApplication sharedApplication] beginBackgroundTaskWithName:@"bg_task" expirationHandler:^{?
?? ? ?[[UIApplication sharedApplication] endBackgroundTask:bgTask]; ?
?? ? ? bgTask = UIBackgroundTaskInvalid; ??
? }];