2. 时间计时器

在你的代码中,leftSecond 的值确实在每次定时器触发时都会更新,但页面没有刷新的原因可能是以下之一:


**1. Date().addingTimeInterval(leftSecond) 的问题**

每次调用 Date().addingTimeInterval(leftSecond) 时,Date() 会返回当前时间,而不是一个固定的基准时间。因此,即使 leftSecond 在减少,Date() 也在不断变化,导致计算结果看起来没有变化。

解决方法:

  • 使用一个固定的基准时间(例如当前时间)来计算剩余时间。

  • 在视图初始化时保存一个基准时间,然后基于这个基准时间计算剩余时间。

修改后的代码:

struct WARoomContentWealthContentView: View {
    @State private var day: Int = 2
    @State private var leftSecond: TimeInterval = 9999
    @State private var startDate: Date = Date() // 保存基准时间
    
    let leftTimer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()

    var body: some View {
        VStack {
            Spacer().frame(height: 12) // 预留高度
            VStack(spacing: 0) {
                Image("icon_room_wealth_dealine")
                    .resizable()
                    .frame(width: 60, height: 17)
                Spacer().frame(height: 6)
                Text("\(day)Day \(startDate.addingTimeInterval(leftSecond).toHourToSecondString())")
                    .systemBoldFont(size: 14)
                    .multilineTextAlignment(.center)
                    .foregroundColor(Color(red: 0.95, green: 0.72, blue: 0))
                    .background(Image("icon_room_wealth_timer_bg"))
                    .frame(width: 207, height: 24)
            }
        }
        .onReceive(leftTimer) { _ in
            if leftSecond > 0 {
                leftSecond -= 1
                print("lt - left second: \(leftSecond)")
            }
        }
    }
}

关键点:

  • 使用 @State private var startDate: Date = Date() 保存一个固定的基准时间。

  • 在 Text 中,使用 startDate.addingTimeInterval(leftSecond) 计算剩余时间。


**2. toHourToSecondString() 的实现问题**

如果 toHourToSecondString() 是一个自定义方法,确保它的实现是正确的。它应该将 Date 转换为 HH:mm:ss 格式的字符串。示例实现:extension Date { func toHourToSecondString() -> String { let formatter = DateFormatter() formatter.dateFormat = "HH:mm:ss" return formatter.string(from: self) } }


3. SwiftUI 视图更新的条件

SwiftUI 的视图更新依赖于 @State、@Binding、@ObservedObject 等状态变量的变化。如果 leftSecond 的值确实在变化,但视图没有更新,可能是以下原因:

  • **视图层级问题**:某些父视图可能阻止了子视图的更新。

  • **视图优化问题**:SwiftUI 可能会优化视图更新,如果它认为视图内容没有变化。

解决方法:

  • 确保 leftSecond 的变化会触发视图更新。可以通过在 Text 中直接打印 leftSecond 来调试:

Text("\(day)Day \(leftSecond)")如果 leftSecond 的值在视图中正确显示并更新,说明问题出在 Date().addingTimeInterval(leftSecond) 或 toHourToSecondString() 的实现上。


4. 调试建议

  • 在 onReceive 中打印 leftSecond 的值,确保它确实在变化。

  • 在 Text 中直接显示 leftSecond,检查视图是否更新。

  • 检查 toHourToSecondString() 的实现,确保它正确地将 Date 转换为字符串。


5. 完整代码

以下是修正后的完整代码:

import SwiftUI

struct WARoomContentWealthContentView: View {
    @State private var day: Int = 2
    @State private var leftSecond: TimeInterval = 9999
    @State private var startDate: Date = Date() // 保存基准时间
    
    let leftTimer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()

    var body: some View {
        VStack {
            Spacer().frame(height: 12) // 预留高度
            VStack(spacing: 0) {
                Image("icon_room_wealth_dealine")
                    .resizable()
                    .frame(width: 60, height: 17)
                Spacer().frame(height: 6)
                Text("\(day)Day \(startDate.addingTimeInterval(leftSecond).toHourToSecondString())")
                    .systemBoldFont(size: 14)
                    .multilineTextAlignment(.center)
                    .foregroundColor(Color(red: 0.95, green: 0.72, blue: 0))
                    .background(Image("icon_room_wealth_timer_bg"))
                    .frame(width: 207, height: 24)
            }
        }
        .onReceive(leftTimer) { _ in
            if leftSecond > 0 {
                leftSecond -= 1
                print("lt - left second: \(leftSecond)")
            }
        }
    }
}

extension Date {
    func toHourToSecondString() -> String {
        let formatter = DateFormatter()
        formatter.dateFormat = "HH:mm:ss"
        return formatter.string(from: self)
    }
}

struct WARoomContentWealthContentView_Previews: PreviewProvider {
    static var previews: some View {
        WARoomContentWealthContentView()
    }
}

总结

  • 使用固定的基准时间(startDate)来计算剩余时间。

  • 确保 toHourToSecondString() 正确实现。

  • 如果问题仍然存在,可以通过调试 leftSecond 的值和视图更新逻辑来定位问题。

总结:

1、定时器的使用

2、注意date时间的减少,要使用一个固定开始的时间,而不是每次都Date() ,这样+1 和减1, 改变前后都是一样的。

Last updated