SwiftUI: Таймер запуска/остановки при появлении/исчезновении вида

#swift #swiftui #timer #uiappearance

#быстрый #свифтуи #таймер #внешний вид

Вопрос:

У меня есть представление, в котором я показываю документ (в основном фоновое изображение с несколькими смайликами на нем). В моем представлении навигации есть несколько документов, и всякий раз, когда я загружаю документ (создается представление документа), я хотел бы запустить таймер (загрузить сохраненное время из пользовательских настроек, если оно существует), чтобы измерить, сколько времени я потратил на работу. Когда я перехожу на другой документ, я хотел бы отменить таймер предыдущих документов (и сохранить время в настройках пользователя) и запустить новый из текущего документа.

Вид:

 struct DocumentView: View { @ObservedObject var document: DocumentViewModel  init(documentViewModel: DocumentViewModel) {  self.document = documentViewModel }  var body: some View {  VStack {  //some UI code here   createTimeTracker()  }.onAppear{ //not called every time view is shown :(  document.startTimeTracker()  }  .onDisappear{  document.stopTimeTracker()  } }  private func createTimeTracker() -gt; some View {  return HStack{  Label("(document.timeSpent) s", systemImage: "timer")  } }  

Документ:

 class DocumentViewModel: ObservableObject, Equatable, Hashable, Identifiable {    let id: UUID    @Published var timeSpent: Int = 0     init(id:UUID = UUID()) {  self.id = id  //some code here  }     func startTimeTracker(){  timeSpent = UserDefaults.standard.integer(forKey: "DocumentViewModel.(id).timeSpent")  print("Starting/Resuming timer at (timeSpent) s")  timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()  subscription = timer?.sink(receiveValue: { _ in  self.updateTimeSpent()  })  }    func stopTimeTracker(){  print("Stopping timer at (timeSpent) s")  UserDefaults.standard.set(timeSpent, forKey: "DocumentViewModel.(id).timeSpent")  self.timer?.upstream.connect().cancel()  }    func updateTimeSpent(){  timeSpent  = 1  }  

Создание представления

 NavigationLink(destination: DocumentView(documentViewModel: document))  

Проблема Я понял, что onAppear вызывается не каждый раз, когда отображается представление документа. Поэтому у меня есть несоответствия в отношении моего таймера при переключении с одного документа на другой(onAppear, похоже, не вызывается). Есть ли лучший способ реализовать поведение onAppear/onDisappear? Использование TimerPublisher является обязательным требованием, проблема заключается в вызове вызовов методов, определенных в onAppear/onDisappear, а не в измерении времени или чем-то еще.

Любой вклад очень ценится!

Комментарии:

1. Не используйте его в представлении (срок службы SwiftUI не подходит для этого)-переосмыслите его использование на уровне модели/представления-модели.

2. что вы имеете в виду под «этим»? Не могли бы вы описать это немного яснее? Спасибо!

3. Почему бы просто не отслеживать время начала и окончания как текущую дату? продолжительность затраченного времени-это просто «интервал времени» между двумя датами. Вам не понадобится таймер, и это будет гораздо более простая реализация. Таймеры больше предназначены для того, чтобы что-то происходило относительно регулярно, и не очень хорошо подходят для чего-то подобного.

4. К сожалению, использование TimerPublisher является обязательным требованием. Использование таймера также не является проблемой здесь, это больше для того, чтобы действовать при появлении/исчезновении представления.