You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

didEnterBackground中发起的网络请求未总能被后端接收问题排查

问题根因分析

首先明确:didEnterBackgroundNotification本身触发逻辑是可靠的,你能通过日志确认方法被调用,就已经说明通知本身没有问题,异常表现来自iOS App生命周期的系统限制,以及你的代码疏漏。

两种场景的核心差异:

  • 切换App进入后台:系统会为App预留3~5秒的时间执行当前未完成的同步/异步任务,之后才会将App进程挂起,你的网络请求足够在这个时间窗口内完成,因此可以正常发送到服务端。
  • 上滑强制退出App:系统触发didEnterBackgroundNotification之后,会立刻启动App终止流程,不会预留额外时间执行异步任务。你封装的Alamofire请求是异步执行的,还没等请求包发送出去,App进程就已经被系统销毁,因此请求无法到达服务端。

你代码的两处核心疏漏:

  • 未申请后台执行权限:iOS允许App进入后台时申请最长约30秒的额外后台执行时间,用于完成未结束的关键任务,你未主动申请的情况下,强制退出场景下没有足够时间执行异步请求。
  • 请求未设置completion回调:你调用request(completion: nil)完全没有监听请求的完成状态,既无法确认请求是否执行成功,也无法在请求完成后主动通知系统任务结束。

修复方案

第一步:声明后台任务标识

在你的视图控制器类中添加后台任务标识属性:

var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid

第二步:调整didEnterBackground实现

修改方法逻辑,先申请后台任务再执行请求,请求完成后主动结束后台任务:

@objc func didEnterBackground() {
    // 申请后台执行权限
    backgroundTaskID = UIApplication.shared.beginBackgroundTask(withName: "SendLessonProgressTask") { [weak self] in
        // 后台任务超时回调,主动结束任务避免被系统强制杀进程
        guard let self = self else { return }
        UIApplication.shared.endBackgroundTask(self.backgroundTaskID)
        self.backgroundTaskID = .invalid
    }

    guard let course = self.focusedCourse.value else { 
        // 没有需要处理的课程,直接结束后台任务
        UIApplication.shared.endBackgroundTask(backgroundTaskID)
        backgroundTaskID = .invalid
        return 
    }

    switch course.status {
    case .finished:
        Worker.PutLessonProgress(lessonID: course.id, progress: Int(playTime.value)).request { [weak self] result in
            guard let self = self else { return }
            // 请求完成(无论成功失败)都主动结束后台任务
            UIApplication.shared.endBackgroundTask(self.backgroundTaskID)
            self.backgroundTaskID = .invalid
        }
    case .live, .upcoming, .todayUpcoming, .free:
        // 不需要处理的状态,直接结束后台任务
        UIApplication.shared.endBackgroundTask(backgroundTaskID)
        backgroundTaskID = .invalid
        break
    }
}

补充说明

就算添加了后台任务逻辑,也无法保证极端场景下请求100%发送成功,比如系统资源极度紧张时,分配给你的后台执行时间可能远小于30秒。如果进度上报的可靠性要求很高,建议你增加本地持久化逻辑:发起请求前先把进度存在本地,请求成功后再删除本地记录,下次App启动时先检查有没有未上报的进度,补发请求即可。

内容的提问来源于stack exchange,提问作者Kex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 04:54:02