swift 如何在每天午夜重置Bool值

sxissh06  于 12个月前  发布在  Swift
关注(0)|答案(2)|浏览(132)

我想要一个布尔值,每天午夜都变成真,有人知道我怎么能做到这一点。这是我到目前为止尝试的代码。我一直得到这些错误:
类型“()”不能符合“View”

泛型结构“ObservedObject”要求"ContentView.Daily“符合”ObservableObject“

import SwiftUI
import Foundation

struct ContentView: View {
    
    class Daily: ObservableObject {
        @Published var timedbool: Bool = false
        private var timer: Timer?
        
        init(){
            scheduleDailyReset()
        }
        private func scheduleDailyReset(){
            let calendar = Calendar.current
            if let tomorrow = calendar.date(byAdding: .day, value: 1, to: calendar.startOfDay(for: Date())) {
                let timeInterval = tomorrow.timeIntervalSinceNow
                timer = Timer.scheduledTimer(timeInterval: timeInterval, target: self, selector: #selector(setBool), userInfo: nil, repeats: false)
        }
    }
        
        @objc func setBool() {
            timedbool = true
            scheduleDailyReset()
        }
        func getBool() -> Bool {
            return timedbool
        }
        }
    
    @State var daily = Daily()
    @State var dailyreset: Bool = daily.getBool()
    
    var body: some View {
        NavigationView {
            VStack{
                if dailyreset{
                    navig2 = true
                }

字符串
我试着用一个函数来做每日重置,然后用另一个函数来返回重置bool值,但它不符合View。

n3h0vuf2

n3h0vuf21#

首先,你的代码有几个问题:
1.对于daily,使用@StateObject而不是@State,因为它是一个可观察的对象,而不是结构。
1.你不能像这样把不产生视图的swift代码放在你的body函数中。如果你想做一些计算,根据你的需要把它们放在onAppearonChange(of:)视图修饰符或类似的东西中。
但实际的问题是,你需要安排一个后台任务,以便在应用程序可能不运行时运行代码,在你的情况下是在午夜。
以下是相关文档的指针:
https://developer.apple.com/documentation/backgroundtasks
最后一点:
我建议你审查你的要求,你真的需要在那个时候运行代码,或者它是足够的重新评估,如果它是一个新的一天,一旦应用程序被用户再次启动,这将是简单得多。

mf98qq94

mf98qq942#

你的计时器没问题。
你的代码中有几个问题:
1.将class Daily代码移到顶层。这将删除@ObservableObject错误。
1.将@State var daily更改为@StateObject。这将使@ObservableObject正确更新。
1.不要将函数getBool()@State一起使用。直接使用@Published var timedbool,就像使用daily.timedbool一样。
1.在body navig2 = true的行中,你返回了一个Bool,而你应该返回一个View。你需要在这里放一个view。
这将是我的改变:

import SwiftUI

class Daily: ObservableObject {
    @Published var timedbool: Bool = false
    private var timer: Timer?
    
    init() {
        scheduleDailyReset()
    }
    private func scheduleDailyReset() {
        let calendar = Calendar.current
        guard let tomorrow = calendar.date(byAdding: .day, value: 1, to: calendar.startOfDay(for: .now)) else {
//        guard let tomorrow = calendar.date(byAdding: .second, value: 5, to: .now) else { // use this instead to test
            print("There's no tomorrow.")
            return
        }
        
        let timeInterval = tomorrow.timeIntervalSinceNow
        timer = Timer.scheduledTimer(timeInterval: timeInterval, target: self, selector: #selector(setBool), userInfo: nil, repeats: false)
        print("timer: \(timer?.fireDate)")
    }
    
    @objc func setBool() {
        timedbool = true
        scheduleDailyReset()
    }
}

struct ContentView: View {
    @StateObject var daily = Daily()
    
    var body: some View {
        VStack {
            Button("Confirm") {
                daily.timedbool = false  // set @Published var
            }
            .disabled(!daily.timedbool) // use @Published var
        }
        .padding()
        .onChange(of: daily.timedbool) { bool in // use @Published var
            print("timed bool set to \(bool)")
        }
    }
}

字符串
请注意,带有按钮的视图只是如何在视图中获取和设置timedbool的示例。
有一个替代的fireDate定义,所以你不必熬夜看它是否有效。
我更喜欢在这里使用guard语句来展开可选的Date,以避免缩进。

相关问题