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

Swift中Timer的使用:能否将Selector绑定到ContentView的函数?

SwiftUI中Timer无法绑定ContentView函数的问题解决

为什么会报错?

ContentView是遵循View协议的值类型struct,而@objc修饰符仅能用于类(class)、@objc协议或类的具体扩展成员,struct不支持@objc,所以直接给ContentView里的update()加@objc会触发Xcode报错。

解决方案

SwiftUI里不推荐直接用OC风格的Selector式Timer,更推荐符合响应式编程的方案,以下是两种可行方式:

方式一:用Combine的Timer.publish(推荐)

将Timer逻辑封装到ObservableObject类中,通过@Published属性向ContentView传递数据:

import SwiftUI
import Combine

class TimerManager: ObservableObject {
    @Published var count = 0
    private var timerCancellable: AnyCancellable?
    
    func start() {
        timerCancellable = Timer.publish(every: 1, on: .main, in: .common)
            .autoconnect()
            .sink { [weak self] _ in
                self?.count += 1
                self?.handleTimerFire()
            }
    }
    
    func stop() {
        timerCancellable?.cancel()
    }
    
    // 类中可以正常使用@objc修饰方法
    @objc private func handleTimerFire() {
        print("Timer触发,执行更新逻辑")
    }
}

struct ContentView: View {
    @StateObject private var timerManager = TimerManager()
    
    var body: some View {
        Text("计数:\(timerManager.count)")
            .onAppear {
                timerManager.start()
            }
            .onDisappear {
                timerManager.stop()
            }
    }
}

方式二:用传统Selector式Timer(兼容OC风格)

如果一定要用Selector,需要把Timer的target放到NSObject子类中,通过闭桥接回ContentView:

import SwiftUI

class TimerTarget: NSObject {
    var onTimerFire: (() -> Void)?
    
    @objc func update() {
        onTimerFire?()
    }
}

struct ContentView: View {
    @State private var count = 0
    private var timer: Timer?
    private let timerTarget = TimerTarget()
    
    var body: some View {
        Text("计数:\(count)")
            .onAppear {
                timerTarget.onTimerFire = { [weak self] in
                    self?.count += 1
                    print("Timer触发")
                }
                timer = Timer.scheduledTimer(
                    timeInterval: 1,
                    target: timerTarget,
                    selector: #selector(TimerTarget.update),
                    userInfo: nil,
                    repeats: true
                )
            }
            .onDisappear {
                timer?.invalidate()
            }
    }
}

总结

SwiftUI的View是struct,无法直接作为Timer的Selector目标,必须将Timer逻辑迁移到class类型的对象中。优先选择Combine的响应式方案,更贴合SwiftUI的数据流设计。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 15:25:50