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

Swift中如何实现定时重复发送HTTP请求?(OHLC数据场景)

嘿,我来帮你搞定这个定时请求OHLC数据的问题~

首先得说清楚你之前用while(true)+sleep(10)为啥不行:

  • sleep(10)会直接阻塞当前线程,如果这段代码跑在主线程,整个App的UI都会卡死,完全没法交互;
  • HTTP请求是异步操作,你发起请求后立刻sleep,根本没等请求返回就进入下一次循环,而且这种死循环会一直占用线程资源,完全不符合iOS的异步运行逻辑。

接下来给你两种靠谱的实现方案,都是结合视图控制器的生命周期,确保只有在视图活跃时才持续请求,切换页面就立刻停止:

方案一:用DispatchSourceTimer(推荐,更可靠)

这种定时器不受主线程RunLoop的影响,适合后台定时任务,不会因为主线程繁忙而延迟触发。

步骤1:在ViewController里声明定时器变量

import UIKit

class YourViewController: UIViewController {
    // 声明定时器,用可选类型方便后续销毁
    private var ohlcTimer: DispatchSourceTimer?
    // 加个标记防止并发请求(比如网络慢时,避免同时发多个请求)
    private var isRequestingOHLC = false
    
    // 其他代码...
}

步骤2:在视图显示时启动定时器

在viewDidAppear里初始化并启动定时器,确保视图活跃时才开始请求:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    
    // 创建定时器,用后台队列执行任务,不阻塞主线程
    ohlcTimer = DispatchSource.makeTimerSource(queue: DispatchQueue.global(qos: .background))
    // 设置触发规则:立刻执行一次,之后每10秒执行,给100ms的容错时间(减少系统资源消耗)
    ohlcTimer?.schedule(deadline: .now(), repeating: .seconds(10), leeway: .milliseconds(100))
    
    // 设置定时器执行的任务
    ohlcTimer?.setEventHandler { [weak self] in
        guard let self = self, !self.isRequestingOHLC else { return }
        
        self.isRequestingOHLC = true
        // 发起OHLC请求
        HTTPRequest.requestOHLC(symbol: "XBTUSD") { ohlcData in
            // 请求完成后重置标记
            defer { self.isRequestingOHLC = false }
            
            // 注意:网络请求的回调在后台线程,更新UI必须切回主线程
            DispatchQueue.main.async {
                // 这里处理你的数据,比如更新图表、列表等
                // do something with ohlcData
            }
        }
    }
    
    // 启动定时器
    ohlcTimer?.resume()
}

步骤3:在视图消失时停止定时器

在viewDidDisappear里销毁定时器,确保页面切换后立刻停止请求:

override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)
    // 取消定时器并置空,避免内存泄漏
    ohlcTimer?.cancel()
    ohlcTimer = nil
}

方案二:用UIKit的Timer(简单易上手)

如果你的需求不那么严格,也可以用系统自带的Timer,不过它依赖主线程的RunLoop,主线程繁忙时可能会延迟触发:

实现代码

class YourViewController: UIViewController {
    private var ohlcTimer: Timer?
    private var isRequestingOHLC = false
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        // 每10秒重复执行一次
        ohlcTimer = Timer.scheduledTimer(withTimeInterval: 10, repeats: true) { [weak self] _ in
            guard let self = self, !self.isRequestingOHLC else { return }
            
            self.isRequestingOHLC = true
            HTTPRequest.requestOHLC(symbol: "XBTUSD") { ohlcData in
                defer { self.isRequestingOHLC = false }
                
                DispatchQueue.main.async {
                    // 处理数据
                }
            }
        }
    }
    
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        // 停止并销毁定时器
        ohlcTimer?.invalidate()
        ohlcTimer = nil
    }
}

关键注意点

  • 避免内存泄漏:一定要用[weak self],因为定时器会持有视图控制器,如果控制器也持有定时器,就会形成循环引用,导致控制器无法被释放;
  • 线程切换:网络请求的回调几乎都是在后台线程,更新UI必须切回主线程(DispatchQueue.main.async),否则会触发崩溃;
  • 防止并发请求:加isRequestingOHLC标记,避免网络慢时同时发起多个请求,造成资源浪费或者数据混乱;
  • 生命周期匹配:用viewDidAppear和viewDidDisappear来启动/停止定时器,完美匹配视图的活跃状态,符合用户的使用场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:09:03