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
相关产品推荐
相关产品推荐

