如何在DispatchQueue中不使用sleep()实现执行延迟且不冻结App
问题原因
你现在直接在主线程的执行闭包里调用sleep()会卡住主线程,而主线程负责所有UI渲染、用户交互响应,阻塞5秒自然会出现App冻结的情况。
解决方法
用GCD的asyncAfter延迟派发API替代sleep()即可,它不会阻塞当前线程,到时间后才会把要执行的逻辑派发到指定线程执行,你要延迟的条件判断、第二个POST请求都可以放到延迟执行的闭包里。
修改后的核心代码
func getStuff() { let server = appState.server + "extension" let package = self.myID guard let url = URL(string: server) else { return } var urlRequest = URLRequest(url: url) urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type") urlRequest.addValue("application/json", forHTTPHeaderField: "Accept") urlRequest.httpMethod = "POST" guard let data = try? JSONEncoder().encode(package) else { return } urlRequest.httpBody = data let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in if let error = error { return } guard let data = data else { return } guard let dataString = String(data: data, encoding: String.Encoding.utf8) else { return } let jsonData = Data(dataString.utf8) var decodedJob: Job? = nil do { decodedJob = try JSONDecoder().decode(Formatter.self, from: jsonData) } catch { print(error.localizedDescription) } DispatchQueue.main.async { self.firstTimeLoading = false // 替换sleep为延迟派发,5秒后执行后续逻辑 DispatchQueue.main.asyncAfter(deadline: .now() + 5) { [weak self] in guard let self = self else { return } if self.array == [] { self.otherPostFunction() } } } } task.resume() }
额外注意点
- 代码里加了
[weak self]的捕获列表,避免如果等待的5秒内当前页面被销毁,导致的内存泄漏或者异常访问问题 - 延迟时间的精度可以满足普通业务需求,如果需要更高精度的计时可以换用
Timer或者CADisplayLink,当前场景用asyncAfter足够简单高效
内容的提问来源于stack exchange,提问作者nickcoding2
相关产品推荐
相关产品推荐

