Reputation: 302
I am trying to create an Image carousel using tabview and loading pictures from firebase. Without showing any error message or code tabview crashing. Please shed some light on what's going wrong here.
struct HomeView : View{
var body : View{
NavigationView{
VStack{
ScrollView{
CategoryView(homeViewModel: homeViewModel)
PosterView(homeViewModel: homeViewModel)
}
}
.navigationBarTitleDisplayMode(.inline)
.navigationBarTitle("")
}
}
}
struct PosterView : View {
@StateObject var homeViewModel : HomeViewModel = HomeViewModel()
@State var currentIndex: Int = 0
var timer = Timer.publish(every: 3, on: .main, in: .common)
func next(){
withAnimation{
currentIndex = currentIndex < homeViewModel.posterList.count ? currentIndex +
1 : 0
}
}
var body: some View{
Divider()
GeometryReader{ proxy in
VStack{
TabView(selection: $currentIndex){
ForEach(homeViewModel.posterList){ item in
let imgURL = homeViewModel.trendingImgDictionary[item.id ?? ""]
AnimatedImage(url: URL(string: imgURL ?? ""))
}
}.tabViewStyle(PageTabViewStyle())
.padding()
.frame(width: proxy.size.width, height: proxy.size.height)
.onReceive(timer) { _ in
next()
}
.onTapGesture {
print("Tapped")
}
}
}
}
}
ViewModel: It contains two methods to fetch data and pictures from Firebase. That's working fine and am getting proper data. The only issue is while displaying it tabview crashes without showing any error messages.
class HomeViewModel : ObservableObject {
@Published var posterList : [TrendingBanner] = []
@Published var trendingImgDictionary : [String : String] = [:]
init() {
self.fetchTrendingList()
}
func fetchTrendingList() {
self.posterList.removeAll()
firestore.collection(Constants.COL_TRENDING).addSnapshotListener { snapshot, error in
guard let documents = snapshot?.documents else{
print("No Documents found")
return
}
self.posterList = documents.compactMap({ (queryDocumentSnapshot) -> TrendingBanner? in
return try? queryDocumentSnapshot.data(as:TrendingBanner.self )
})
print("Trending list \(self.posterList.count)")
print(self.posterList.first?.id)
let _ = self.posterList.map{ item in
self.LoadTrendingImageFromFirebase(id: item.id ?? "")
}
}
}
func LoadTrendingImageFromFirebase(id : String) {
let storageRef = storageRef.reference().child("trending/\(id)/\(id).png")
storageRef.downloadURL { (url, error) in
if error != nil {
print((error?.localizedDescription)!)
return
}
self.trendingImgDictionary[id] = url!.absoluteString
print("Trending img \(self.trendingImgDictionary)")
}
}
Upvotes: 1
Views: 1058
Reputation: 91
Had the same issue recently on devices running iOS 14.5..<15. Adding .id()
modifier to the TabView
solved it.
Example:
TabView(selection: $currentIndex) {
ForEach(homeViewModel.posterList) { item in
content(for: item)
}
}
.tabViewStyle(PageTabViewStyle())
.id(homeViewModel.posterList.count)
Upvotes: 0
Reputation: 6030
If you open SwiftUI module sources, you'll see the comment on top of TabView
:
Tab views only support tab items of type
Text
,Image
, or an image followed by text. Passing any other type of view results in a visible but empty tab item.
You're using AnimatedImage
which is probably not intended to be supported by TabView
.
Update
I made a library that liberates the SwiftUI _PageView
which can be used to build a nice tab bar. Check my story on that.
Upvotes: 1