iOS Swift开发:如何让指定操作10秒未完成时终止并执行备选逻辑
实现方案
优先推荐使用苹果官方推荐的URLSession替换已经废弃的NSURLConnection接口,稳定性和可控性更好,两种实现方式如下:
方案1:使用URLSession实现(推荐)
直接给URLRequest设置timeoutInterval属性为10(单位为秒),请求超过10秒未完成会自动终止并触发错误回调,在错误分支执行你的备选逻辑即可:
let database = "https://example.com" let databaseURL = URL(string: database)! // 直接设置10秒超时 var databaseRequest = URLRequest(url: databaseURL, timeoutInterval: 10) databaseRequest.httpMethod = "GET" URLSession.shared.dataTask(with: databaseRequest) { [weak self] data, response, error in // 切回主线程处理UI和文件操作 DispatchQueue.main.async { // 判断是否请求失败/超时/无返回数据 guard let data = data, error == nil else { // 执行备选逻辑 print("ERROR: Could not retrieve list.") let warningToUser = UIAlertController(title: "错误", message: "无法获取您的偏好设置,已重置为默认值,下次启动应用时会再次尝试。", preferredStyle: .alert) warningToUser.addAction(UIAlertAction(title: "确定", style: .default)) self?.present(warningToUser, animated: true) return } // 原写入文件逻辑 let databaseFile = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("local.txt") do { try data.write(to: databaseFile) } catch { print(error.localizedDescription) } } }.resume()
方案2:保留原有NSURLConnection写法
如果需要兼容旧代码,直接给原有的URLRequest设置超时属性,在回调里判断错误类型即可:
let database = "https://example.com" let databaseURL = URL(string: database)! var databaseRequest = URLRequest(url: databaseURL) databaseRequest.httpMethod = "GET" databaseRequest.timeoutInterval = 10 // 设置10秒超时 NSURLConnection.sendAsynchronousRequest(databaseRequest, queue: OperationQueue.main) { [weak self] response, data, error in guard let data = data, error == nil else { // 超时或请求失败走备选逻辑 print("ERROR: Could not retrieve list.") let warningToUser = UIAlertController(title: "错误", message: "无法获取您的偏好设置,已重置为默认值,下次启动应用时会再次尝试。", preferredStyle: .alert) warningToUser.addAction(UIAlertAction(title: "确定", style: .default)) self?.present(warningToUser, animated: true) return } // 原写入文件逻辑 let databaseFile = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("local.txt") do { try data.write(to: databaseFile) } catch { print(error.localizedDescription) } }
注意事项
- 不需要额外自己实现定时器监控超时,系统原生的
timeoutInterval会自动在超时后终止请求并触发错误回调,性能更高也更准确 - 所有UI相关操作必须放在主线程执行,URLSession的默认回调在后台线程,需要手动切到主队列,避免UI异常或崩溃
- 回调中使用
[weak self]避免循环引用,防止内存泄漏
内容的提问来源于stack exchange,提问作者anon
相关产品推荐
相关产品推荐

