使用tabview更改选项卡时如何使SwiftUI中的计时器保持触发
Posted
技术标签:
【中文标题】使用tabview更改选项卡时如何使SwiftUI中的计时器保持触发【英文标题】:How to make a timer in SwiftUI keep firing when changing tab with tabview 【发布时间】:2020-01-20 03:02:10 【问题描述】:我有一个计时器,它每半秒触发一次,这会导致调用一个函数,该函数输出一组字符串,用于显示特定日期的倒计时。当我创建一个新事件然后切换到包含倒计时信息的选项卡时它可以工作,但是当我切换回添加事件选项卡然后返回时它会停止倒计时。
计时器是用这个制作的:
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】:它需要将.onReceive
附加到TabView
,它将在所有选项卡上接收,例如
TabView
...
// << all tab items here
...
.onReceive(self.timer) _ in
self.differenceDate()
并在处理程序内部迭代索引
func differenceDate()
for numbers in eventNames.indices
// current body here
【讨论】:
以上是关于使用tabview更改选项卡时如何使SwiftUI中的计时器保持触发的主要内容,如果未能解决你的问题,请参考以下文章
使用 SwiftUI 的 TabbedView 切换到其他选项卡时查看内容不显示
从一个选项卡滑动到另一个选项卡时,TabView 不保留状态