Swift应用后台AES加密耗时过长无法完成问题排查
问题原因分析及解决方案
核心原因
无意义的信号量操作加剧后台线程阻塞
你代码里的DispatchSemaphore完全是多余且逻辑错误的:创建初始值为0的信号量后立刻调用signal(),紧接着又wait(),这两行代码除了浪费线程调度资源外没有任何作用。前台环境下系统线程调度优先级高,这个无效操作不会引发明显问题,但后台环境中系统对线程资源管控更严格,这种无意义的等待会增加线程被系统挂起的概率。iOS后台CPU时间限制
iOS应用进入后台后,系统会大幅限制应用的CPU使用权限,普通线程会被暂停执行,直到应用回到前台。如果你的加密操作没有通过后台任务断言申请延长后台执行时间,系统会直接暂停加密所在的线程,导致任务停滞。加密库的线程执行环境依赖
你使用的AES加密库(大概率是CryptoSwift)的同步加密方法在当前线程执行,如果当前线程是主线程,后台时主线程会被系统强制挂起;如果是普通后台线程,同样会因为系统的后台资源限制而被暂停。
修复方案
移除无效的信号量代码
直接删掉这三行无意义的信号量操作:let semaphore = DispatchSemaphore(value: 0) semaphore.signal() semaphore.wait()申请后台任务权限以延长执行时间
如果需要在后台完成加密,必须通过UIApplication的后台任务断言来申请额外的执行时间:func crypt(dados: String, sistema: String, completion: @escaping (String) -> Void) { var backgroundTaskID: UIBackgroundTaskIdentifier = .invalid backgroundTaskID = UIApplication.shared.beginBackgroundTask(withName: "AES加密任务") { // 任务超时或系统强制结束时的清理操作 UIApplication.shared.endBackgroundTask(backgroundTaskID) backgroundTaskID = .invalid } DispatchQueue.global(qos: .background).async { let key = "ie2kiei2-\(sistema)" let key_p = key.leftPadding(toLength: 32, withPad: "0") var result = "erro" do { let aes = try AES(key: key_p, iv: "12493274392") let ciphertext = try aes.encrypt(Array(dados.utf8)) let data = Data(bytes: ciphertext, count: ciphertext.count) result = data.base64EncodedString() } catch { print(error) } DispatchQueue.main.async { completion(result) // 任务完成后结束后台任务断言 if backgroundTaskID != .invalid { UIApplication.shared.endBackgroundTask(backgroundTaskID) backgroundTaskID = .invalid } } } }确保加密操作在低优先级后台线程执行
把加密任务放到全局后台队列执行,避免占用主线程或高优先级线程,让系统更合理地调度后台资源。
额外注意事项
- 后台任务断言的执行时间有限制(通常最多几分钟),如果加密的数据量极大,可能需要拆分任务或考虑其他方案。
- 检查AES初始化代码:
iv: "12493274392"的长度是否符合AES要求(比如AES-256需要16字节IV),长度不符合可能导致加密库内部异常,在后台环境下表现为停滞。
内容的提问来源于stack exchange,提问作者Lucca Germano
相关产品推荐
相关产品推荐

