Reputation:
I can not understand why the timer does not work, and the text does not scroll automatically.
I tried to do so:
ForEach(0..<numberText)
But I got such an error:
Referencing initializer 'init(_:content:)' on 'ForEach' requires that 'some View' conform to 'TableRowContent'
Full code:
let numberText = ["text1","text2","text3","text4"]
struct TextNew: View {
private let timer = Timer.publish(every: 3, on: .main, in: .common).autoconnect()
@State private var index = 0
let textdata = TextData.getAllText()
var body: some View {
GeometryReader { proxy in
TabView(selection: $index) {
ForEach(numberText, id: \.self) { num in
Text("\(num)")
.font(.system(size: 10))
.foregroundColor(.white)
.tag(num)
.padding(.bottom, 50)
}
}
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
.frame(height: 80)
.onReceive(timer, perform: { _ in
withAnimation {
index = index < numberText.count ? index + 1 : 0
}
})
}
}
}
Thanks for any help, I'm new
Upvotes: 3
Views: 2359
Reputation: 1579
Improved version of @burnsi 's answer.
//Properties
@StateObject var vm = HomeVVM()
private let timer = Timer.publish(every: 5, on: .main, in: .common).autoconnect()
@State private var index = 1
@State private var selectedNum: String = ""
//Tabview
TabView(selection: $selectedNum) {
ForEach(vm.trendingItems) { item in
HomeSliderItem(image: item.getImage(), text: item.getName()).tag(item.id.uuidString)
}
}
.tabViewStyle(.page)
.onChange(
of: selectedNum,
{ oldValue, newValue in
let newIndex = vm.trendingItems.firstIndex(where: { it in
it.id.uuidString == selectedNum
})
index = newIndex != nil ? newIndex! : 1
}
)
.onReceive(
timer,
perform: { _ in
withAnimation {
index = index < vm.trendingItems.count ? index + 1 : 1
let newCandidate = index - 1
if newCandidate > -1 && newCandidate < vm.trendingItems.count {
selectedNum = vm.trendingItems[newCandidate].id.uuidString
}
}
})
✅ It makes sure your app doesn't crash due to an ArrayOutOfBounds exception
✅ Synchronized with the user's scrolling of the TabView
Upvotes: 0
Reputation: 7754
Try this:
struct TextNew: View {
private let timer = Timer.publish(every: 3, on: .main, in: .common).autoconnect()
@State private var index = 1
@State private var selectedNum: String = ""
var body: some View {
GeometryReader { proxy in
TabView(selection: $selectedNum) {
ForEach(numberText, id: \.self) { num in
Text("\(num)")
.font(.system(size: 10))
.foregroundColor(.white)
.padding(.bottom, 50)
}
}
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .never))
.onReceive(timer, perform: { _ in
withAnimation {
index = index < numberText.count ? index + 1 : 1
selectedNum = numberText[index - 1]
}
})
}
}
}
The reason for this not working is the type mismatch between your .tag
and the $index
in your TabView
declaration. These have to match. By the way you do not need the .tag
here as you are setting it to .self
in your ForEach
loop.
Upvotes: 5