【问题标题】:SwiftUI Alert does not dismiss when timer is running计时器运行时,SwiftUI 警报不会关闭
【发布时间】:2021-10-22 17:41:59
【问题描述】:

半相关问题:SwiftUI ActionSheet does not dismiss when timer is running

我目前正在处理的项目中遇到警报问题。当后台运行计时器时,呈现的警报不会消失。大多数情况下,它需要多次单击解除按钮才能消失。我在示例项目中以尽可能少的开销重新创建了这个问题。

我的主要项目在尝试在不同视图上显示警报时出现此问题,但我无法在示例项目中重现该问题。通过在计时器正在运行的同一视图上切换警报,可以可靠地复制该问题。我还通过从文本字段中删除绑定来阻止文本字段视图更新进行了测试。第一次单击时警报仍然无法消除。我不确定是否有办法解决这个问题,并且正在寻找任何可能的建议。

Xcode 13.0/iOS 15.0 也出现在 iOS 14.0 中

Timerview.swift

struct TimerView: View {
    @ObservedObject var stopwatch = Stopwatch()
    @State var isAlertPresented:Bool = false
    var body: some View {
        VStack{
            Text(String(format: "%.1f", stopwatch.secondsElapsed))
                 .font(.system(size: 70.0))
                 .minimumScaleFactor(0.1)
                 .lineLimit(1)
            Button(action:{
                stopwatch.actionStartStop()
            }){
                Text("Toggle Timer")
            }
            
            Button(action:{
                isAlertPresented.toggle()
            }){
                Text("Toggle Alert")
            }
        }
        .alert(isPresented: $isAlertPresented){
            Alert(title:Text("Error"),message:Text("I  am presented"))
        }  
    }
}

秒表.swift

class Stopwatch: ObservableObject{
    @Published var secondsElapsed: TimeInterval = 0.0
        @Published var mode: stopWatchMode = .stopped
        
    
    func actionStartStop(){
        if mode == .stopped{
            start()
        }else{
            stop()
        }
    }
    
    var timer = Timer()
    func start() {
        secondsElapsed = 0.0
        mode = .running
        timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in
            self.secondsElapsed += 0.1
        }
    }
    
    func stop() {
        timer.invalidate()
        mode = .stopped
    }
    
    enum stopWatchMode {
        case running
        case stopped
    }
}

编辑: 将按钮移动到自定义视图解决了最初的问题,但是当按钮需要与 Observable 对象交互时,是否有解决方案?

         Button(action:{
             do{
                 try stopwatch.actionDoThis()
             }catch{
                 isAlertPresented = true
             }
         }){
          Text("Toggle Alert")
         }.alert(isPresented: $isAlertPresented){
          Alert(title:Text("Error"),message:Text("I  am presented"))

【问题讨论】:

    标签: ios swift swiftui alert


    【解决方案1】:

    每次计时器运行时 UI 都会重新创建,因为“secondsElapsed”是一个可观察对象。 SwiftUI 将自动监控“secondsElapsed”的变化,并重新调用视图的 body 属性。 为了避免这种情况,我们需要将按钮和警报分开到另一个视图,如下所示。

    struct TimerView: View {
       @ObservedObject var stopwatch = Stopwatch()
       @State var isAlertPresented:Bool = false
       var body: some View {
         VStack{
            Text(String(format: "%.1f", stopwatch.secondsElapsed))
                .font(.system(size: 70.0))
                .minimumScaleFactor(0.1)
                .lineLimit(1)
            Button(action:{
                stopwatch.actionStartStop()
            }){
                Text("Toggle Timer")
            }
            CustomAlertView(isAlertPresented: $isAlertPresented)
        }
      }
    }
    
    struct CustomAlertView: View {
      @Binding var isAlertPresented: Bool
        var body: some View {
           Button(action:{
            isAlertPresented.toggle()
           }){
            Text("Toggle Alert")
           }.alert(isPresented: $isAlertPresented){
            Alert(title:Text("Error"),message:Text("I  am presented"))
        }
      }
    }
    

    【讨论】:

    • 谢谢,最终这确实解决了原来的问题,但让我意识到我可能没有提出完全更正的问题。如果在计时器仍在运行时按钮与观察到的对象交互后会引发警报,情况会怎样?类似action: { do{try stopwatch.actionDoThis()}catch{isAlertPresented = true}
    • 它会工作的,你有什么问题吗。 Button(action:{ isAlertPresented = true do{try stopwatch.actionDoThis()}catch{isAlertPresented = true}}){Text("Next button")} func actionDoThis () throws { self.secondsElapsed += 0.1 }
    • 事实上,我只是犯了一个没有受过教育的错误。当没有理由让它成为观察对象时,我在自定义警报视图中创建了另一个 @ObservedObject 秒表。我认为提供了澄清,我将在 swiftui 中阅读更多关于状态管理的内容。谢谢!
    猜你喜欢
    • 2020-11-22
    • 1970-01-01
    • 2021-09-23
    • 1970-01-01
    • 2021-09-14
    • 1970-01-01
    • 1970-01-01
    • 2022-12-07
    • 1970-01-01
    相关资源
    最近更新 更多