Swift中如何确保从谷歌服务器安全获取UTC时间后再执行后续代码?
从谷歌服务器获取UTC时间并确保数据就绪后执行后续代码
首先,咱们得明确核心需求:必须等待UTC时间数据成功获取后,再执行后续逻辑,同时要把时间存成字符串。之前代码不稳定大概率是因为没正确处理异步逻辑——网络请求是异步的,如果你在请求还没完成就去访问变量,自然会出问题。
下面给你两种靠谱的实现方案,分别适配不同iOS版本:
方案一:用Async/Await(iOS 15+ 推荐)
这个方案代码更简洁易读,是苹果现在主推的异步编程方式:
import Foundation // 定义获取UTC时间的异步函数 func fetchGoogleUTCTime() async throws -> String { guard let url = URL(string: "https://www.google.com") else { throw NSError(domain: "InvalidURL", code: 0, userInfo: [NSLocalizedDescriptionKey: "无法构建谷歌服务器URL"]) } let (_, response) = try await URLSession.shared.data(from: url) // 从响应头中提取Date字段(服务器返回的是标准UTC格式) guard let httpResponse = response as? HTTPURLResponse, let utcDateString = httpResponse.allHeaderFields["Date"] as? String else { throw NSError(domain: "TimeFetchFailed", code: 1, userInfo: [NSLocalizedDescriptionKey: "无法从响应中获取UTC时间"]) } return utcDateString } // 使用示例(必须在异步上下文调用,比如ViewController的viewDidLoad里用Task) func useUTCTime() { Task { do { let utcTimeString = try await fetchGoogleUTCTime() // 这里就是拿到时间后的后续逻辑,比如存到变量、更新UI等 print("获取到的UTC时间:\(utcTimeString)") // 你可以把utcTimeString赋值给你的全局/实例变量 // self.storedUTCTime = utcTimeString // 执行后续代码,比如更新UI或者其他操作 self.performAfterTimeFetched(time: utcTimeString) } catch { print("获取UTC时间失败:\(error.localizedDescription)") // 处理错误,比如提示用户 } } } // 后续逻辑的示例函数 func performAfterTimeFetched(time: String) { print("开始执行后续逻辑,当前UTC时间:\(time)") // 这里写你需要在拿到时间后做的事情 }
为什么这个方案可靠?
- Async/Await强制让你在拿到结果后再执行后续代码,避免了回调嵌套或者提前访问未初始化的变量
- 从响应头的
Date字段拿时间,比解析页面内容更稳定,谷歌的服务器一定会返回这个字段 - 完整的错误处理,不会因为网络问题、解析失败导致崩溃
方案二:用Completion Handler(兼容iOS 13及以下)
如果需要适配旧系统,就用传统的闭包回调方式:
import Foundation func fetchGoogleUTCTime(completion: @escaping (Result<String, Error>) -> Void) { guard let url = URL(string: "https://www.google.com") else { let error = NSError(domain: "InvalidURL", code: 0, userInfo: [NSLocalizedDescriptionKey: "无法构建谷歌服务器URL"]) completion(.failure(error)) return } let task = URLSession.shared.dataTask(with: url) { _, response, error in if let error = error { completion(.failure(error)) return } guard let httpResponse = response as? HTTPURLResponse, let utcDateString = httpResponse.allHeaderFields["Date"] as? String else { let error = NSError(domain: "TimeFetchFailed", code: 1, userInfo: [NSLocalizedDescriptionKey: "无法从响应中获取UTC时间"]) completion(.failure(error)) return } completion(.success(utcDateString)) } task.resume() } // 使用示例 func useUTCTime() { fetchGoogleUTCTime { result in switch result { case .success(let utcTimeString): print("获取到的UTC时间:\(utcTimeString)") // 存到变量并执行后续逻辑 // self.storedUTCTime = utcTimeString self.performAfterTimeFetched(time: utcTimeString) case .failure(let error): print("获取UTC时间失败:\(error.localizedDescription)") } } // 注意:这里不能直接访问utcTimeString,因为请求还没完成!所有后续逻辑必须放在completion闭包里 } // 后续逻辑的示例函数 func performAfterTimeFetched(time: String) { print("开始执行后续逻辑,当前UTC时间:\(time)") // 这里写你需要在拿到时间后做的事情 }
关键注意事项
- 所有依赖UTC时间的代码必须放在completion闭包(或Async/Await的do块)内部,绝对不能在调用
fetchGoogleUTCTime后直接写后续代码——因为网络请求是异步的,此时时间还没拿到 - 一定要处理错误情况:网络断开、服务器无响应、字段缺失等,不然遇到异常会崩溃或者静默失败
- 为什么用谷歌的主页而不是专门的时间API?因为谷歌的主页高可用,而且响应头的Date字段是标准的RFC 1123格式(比如
Wed, 15 Nov 2023 12:34:56 GMT),直接就是字符串,不需要额外解析
内容的提问来源于stack exchange,提问作者Justin
相关产品推荐
相关产品推荐

