Swift:结构中计时器的问题



我正在构建一个SwiftUI应用程序,并将所有与UI相关的东西都放在一个全局可观察类UILogic中。该类本身有一个名为bp的@Published变量,其类型为BoxParameters(struct(。

我的SwiftUI视图观察这个发布的变量,它有很多组件:aspectRatio、frameWidth、xOffset、yOffset等。例如,如果我想让我的视图更宽,我只需要像这样调用setWidth((函数:

struct BoxParameters {
private(set) var frameWidth: CGFloat = 175

mutating func setWidth(newWidth: Double) {
self.frameWidth = newWidth
}
}

class UILogic: ObservableObject {
@Published var bp = BoxParameters

func doubleWidth() { 
bp.setWidth(bp.frameWidth * 2) 
} 
}

这很好:因为它正在发生变化,所以它创建了一个新的结构实例,该实例触发@Published发送更新,并且视图会随着新的宽度而更改。

我正在努力做的是用计时器更改frameWidth(或任何其他结构变量(。假设我不想立即改变这个值,而是想通过每秒增加10次来改变它。

我的第一个猜测是直接使用计时器:

mutating func setWidth(newWidth: Double, slow: Bool = false) {
if !slow {
self.frameWidth = newWidth
} else {        
Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in
self.frameWidth += 1
if self.frameWidth >= newWidth  {
self.frameWidth = newWidth
timer.invalidate()
}
}
}
}

此代码未编译并引发错误:Escaping closure captures mutating 'self' parameter

这已经让我有点头疼了,所以我开始四处寻找解决方案:https://stackoverflow.com/a/47173607/12596719\https://developer.apple.com/forums/thread/652094\

这两个线程引发了我的问题可能最终得到解决的希望,但这并没有改变任何事情:编译器仍然在抱怨。

这个线程似乎解决了我的问题,所以我试图在我的代码中调整它(只是为了测试它是一个void函数,只会将frameWidth增加50(:

struct BoxParameters {
...
var timerLogic: TimerLogic!
class TimerLogic {
var structRef: BoxParameters!
var timer: Timer!
init(_ structRef: BoxParameters){
self.structRef = structRef;
self.timer = Timer.scheduledTimer(
timeInterval: 0.1,
target: self,
selector: #selector(timerTicked),
userInfo: nil,
repeats: true)
}
func stopTimer(){
self.timer?.invalidate()
self.structRef = nil
}
@objc private func timerTicked(){
self.structRef.timerTicked()
}
}
mutating func startTimer(){
print("Start Timer")
self.timerLogic = TimerLogic(self)
}
mutating func stopTimer() {
print("Stop Timer")
self.timerLogic.stopTimer()
self.timerLogic = nil
}

mutating func timerTicked(){
self.frameWidth += 50
print("Timer: new frame width: (self.frameWidth)")
}
}

预期行为:它将frameWidth增加了50
发生的情况:它打印出框架宽度增加了50(打印值是正确的(,但没有任何变化。但是:如果我手动调用函数timerPicked,frameWidth会按预期更改50!啊!

我认为发生的情况是,计时器在不更改实际结构的情况下更改了结构副本的frameWidth,但timerTicked函数应该更改父结构本身。(因为self.(

有人知道解决这个问题的方法吗?将结构更改为观察到的类本来是一种选择,但由于Swift的设计,@Published类中@Published变量的更改不会通知SwiftUI更改。。。

为什么要把类和任何代码逻辑放在结构中?我认为您需要将逻辑处理成类,只需将结构用于简单的变量用法。

结构最好用于调用应用程序周围的变量。

struct AllstructFittings {
static var collectedWorks: Bool = false
static var collected: String = "notcollected"
static var failclicked: Bool = false
}

https://www.appypie.com/struct-vs-class-swift-how-to

最新更新