SwiftUI ActionSheet не закрывается, когда таймер запущен - PullRequest
1 голос
/ 02 августа 2020

У меня есть следующая простая установка SwiftUI. Таймер, который работает и обновляет текст. Если таймер не запущен (остановлен или приостановлен), я могу легко показать ActionSheet (нажав на «Действия») и закрыть его, выбрав вариант «Отмена» или «Действие 1». Но если таймер работает, мне очень трудно закрыть ActionSheet, выбрав один из вариантов «Отмена» или «Действие 1». Вы знаете, что происходит?

Я использую Xcode 11.5.

import SwiftUI

struct ContentView: View {
    
    @ObservedObject var stopWatch = StopWatch()
    @State private var showActionSheet: Bool = false
    
    var body: some View {
        VStack {
            Text("\(stopWatch.secondsElapsed)")
            HStack {
                if stopWatch.mode == .stopped {
                    Button(action: { self.stopWatch.start() }) {
                        Text("Start")
                    }
                } else if stopWatch.mode == .paused {
                    Button(action: { self.stopWatch.start() }) {
                        Text("Resume")
                    }
                } else if stopWatch.mode == .running {
                    Button(action: { self.stopWatch.pause() }) {
                        Text("Pause")
                    }
                }
                Button(action: { self.stopWatch.stop() }) {
                    Text("Reset")
                }
            }
            Button(action: { self.showActionSheet = true }) {
                Text("Actions")
            }
            .actionSheet(isPresented: $showActionSheet) {
                ActionSheet(title: Text("Actions"), message: nil, buttons: [.default(Text("Action 1")), .cancel()])
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
import SwiftUI

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

1 Ответ

1 голос
/ 02 августа 2020

Прекрасно работает с Xcode 12 / iOS 14, но попробуйте отделить кнопку с листом в другом подвиде, чтобы не воссоздать ее при refre счетчика таймера sh.

Протестировано с Xcode 12 / iOS 14

struct ContentView: View {

    @ObservedObject var stopWatch = StopWatch()
    // @StateObject var stopWatch = StopWatch()       // << used for SwiftUI 2.0
    @State private var showActionSheet: Bool = false

    var body: some View {
        VStack {
            Text("\(stopWatch.secondsElapsed)")
            HStack {
                if stopWatch.mode == .stopped {
                    Button(action: { self.stopWatch.start() }) {
                        Text("Start")
                    }
                } else if stopWatch.mode == .paused {
                    Button(action: { self.stopWatch.start() }) {
                        Text("Resume")
                    }
                } else if stopWatch.mode == .running {
                    Button(action: { self.stopWatch.pause() }) {
                        Text("Pause")
                    }
                }
                Button(action: { self.stopWatch.stop() }) {
                    Text("Reset")
                }
            }
            ActionsSubView(showActionSheet: $showActionSheet)
        }
    }
}

struct ActionsSubView: View {
    @Binding var showActionSheet: Bool
    var body: some View {
        Button(action: { self.showActionSheet = true }) {
            Text("Actions")
        }
        .actionSheet(isPresented: $showActionSheet) {
            ActionSheet(title: Text("Actions"), message: nil, buttons: [.default(Text("Action 1")), .cancel()])
        }
    }
}
...