Как сделать так, чтобы таймер в SwiftUI продолжал срабатывать при смене вкладки с tabview - PullRequest
1 голос
/ 20 января 2020

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

Таймер сделано с использованием этого:

    let timer = Timer.publish(every: 0.5, on: .main, in: .common).autoconnect()

Он запускается позже с использованием этого

ForEach(eventNames.indices, id: \.self) { index in


                    VStack{
                        Text("Your event " + "\(self.eventNames[index])" + " is in " + "\(self.string[index])")
                        .onReceive(self.timer) { input in
                        self.differenceDate(numbers: index)

                        }
                    }


                }

И, наконец, он вызывает эту функцию

func differenceDate(numbers: Int) {
        self.formatter.unitsStyle = .full
        self.formatter.allowedUnits = [.day, .hour, .minute, .second]
        //self.formatter.maximumUnitCount = 2
        self.now = Date();
        if self.now > self.eventDates[numbers] {
            self.eventNames[numbers] = "";
        }
        else {
        self.string[numbers] = self.formatter.string(from: self.now, to: self.eventDates[numbers]) ?? ""
        }

        }

Это полный код


import SwiftUI

struct ContentView: View {
    @State private var selection = 0
    @State private var eventDates = [Date]()
    @State private var eventNames = [String]()
    @State private var currentName = "";
    @State private var counter = 0;
    @State private var placeholderText = "Event Name";
    @State private var selectedDate = Date();
    var numbers = 0;
    let timer = Timer.publish(every: 0.5, on: .main, in: .common).autoconnect()
    @State var now = Date();
    @State var string = [String]();
    var formatter = DateComponentsFormatter();
    func differenceDate(numbers: Int) {
        self.formatter.unitsStyle = .full
        self.formatter.allowedUnits = [.day, .hour, .minute, .second]
        //self.formatter.maximumUnitCount = 2
        self.now = Date();
        if self.now > self.eventDates[numbers] {
            self.eventNames[numbers] = "";
        }
        else {
        self.string[numbers] = self.formatter.string(from: self.now, to: self.eventDates[numbers]) ?? ""
        }

        }
    var body: some View {
        TabView(selection: $selection){
            //Page 1
            VStack{
                Text("Add New Event")
                .underline()
                .font(.title)
                .padding(15)


//                        .onReceive(self.timer) { input in
//                        self.differenceDate(numbers: index)
//                        //}
//                        }
                  //  .minimumScaleFactor(0.1)




                TextField("\(placeholderText)", text: $currentName)
                .padding(10)
                .overlay(
                    RoundedRectangle(cornerRadius: 5)
                        .stroke(Color.gray, lineWidth: 1)
                    .padding(5)
                )



               Text("When is your event?")
                DatePicker("Please enter a date", selection: $selectedDate, displayedComponents: .date)
                    .labelsHidden()
                    .scaledToFill()
                Button(action: {
                    if self.currentName != "" {
                    self.eventNames.append(self.currentName)
                    self.eventDates.append(self.selectedDate)
                    self.string.append("")

                    self.currentName = "";
                    }

                })

                {
                    Text("Add Event")
                        .font(.headline)
                        .foregroundColor(.black)
                }
                .padding(25)

                .overlay(
                    RoundedRectangle(cornerRadius: 5)
                    .stroke(Color.gray, lineWidth: 3)
                    .padding(5)
                )



            }
                //Tab 1
                .tabItem {
                    VStack {
                        Image(systemName: "calendar")
                        Text("Add Event")
                    }
                }
                .tag(1)

            //Page 2
            VStack{

                Text("Your Events").underline()
                .font(.title)
                .padding(15)


                ForEach(eventNames.indices, id: \.self) { index in


                    VStack{
                        Text("Your event " + "\(self.eventNames[index])" + " is in " + "\(self.string[index])")
                        .onReceive(self.timer) { input in
                        self.differenceDate(numbers: index)

                        }
                    }


                }


            }

                //Tab 2
                .font(.title)
                .tabItem {
                    VStack {
                        Image(systemName: "flame.fill")
                        Text("Countdowns")
                    }
                }
                .tag(0)
        }
    }
}

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

Мне было интересно, есть ли обходной путь или как сохранить срабатывание таймера при изменении вкладки, или приостановить его при изменении вкладки, а затем запустить его снова, когда вкладка переключается обратно.

1 Ответ

0 голосов
/ 20 января 2020

Необходимо присоединить .onReceive к TabView, и оно будет получено на всех вкладках, например

TabView {
...
// << all tab items here
...
}
.onReceive(self.timer) { _ in
    self.differenceDate()
}

, и выполнять итерации индексов внутри обработчика

func differenceDate() {
   for numbers in eventNames.indices {
     // current body here
   }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...