I have this overlay view and when a button is pressed it's supposed to refresh the view by calling a function in the view model. The code does work on the app itself but doesn't work within the preview and I'm guessing it's because the environment variables don't contain any data as they're below the level where data is entered. In the app, the data comes from the FeedView and is passed to the children.
The view structure is FeedView -> ReaderView -> ReaderOverlay. When the button is pressed on the preview for FeedView it works properly but it doesn't work properly in ReaderView or ReaderOverlay.
Here's the code for ReaderView:
struct ReaderView: View {
@State var chapter: ChapterInfo
@StateObject private var reader = ReaderViewModel()
@EnvironmentObject var mangaFeed: FeedViewModel
@EnvironmentObject var ch: ChapterIndex
@State private var isTapped = false
@State private var selected: Int = 0 //used in tabview
@State var currentPage = 1
@State var totalPages = 0
var body: some View {
TabView(selection: $selected){
ForEach(Array(reader.pages.enumerated()), id: \.element) { index, element in
Page(page: element)
.tag(index)
.onChange(of: selected){ val in
currentPage = val + 1 //tracks changes in selected tab to display page numbers
}
}
}
.tabViewStyle(.page(indexDisplayMode: PageTabViewStyle.IndexDisplayMode.never))
.onTapGesture(){
isTapped.toggle() // when this is tapped the overlay for control will be toggled
}
.overlay(alignment: .top){
if isTapped{
readerOverlay(chapter: chapter, currentPage: $currentPage, totalPages: reader.pages.count)
.environmentObject(reader)
}
}
.task{
await reader.populate(chapterID: chapter.id)
}
}
}
And the code for ReaderOverlay with its preview is as follows:
struct readerOverlay: View {
@State var nextChapter: ChapterInfo?
@State var chapter: ChapterInfo
@EnvironmentObject var mangaFeed: FeedViewModel
@EnvironmentObject var reader: ReaderViewModel
@EnvironmentObject var ch: ChapterIndex
@Binding var currentPage: Int
@State var totalPages: Int
@Environment(\.dismiss) var dismiss
var body: some View {
VStack{
//the proxy inherits the size of the parent view which in this case is just the screen
GeometryReader{ proxy in
RoundedRectangle(cornerRadius: 15)
.overlay(
HStack{
VStack(alignment: .leading){
//Displays name of the manga
Text(chapter.relationships.first{
$0.type == "manga"
}?.attributes?.title["en"] ?? "")
.font(.headline)
.fontWeight(.medium)
.foregroundColor(.white)
.lineLimit(1)
//Displays name of the chapter
Text("Ch \(chapter.attributes.chapter ?? "") - \(chapter.attributes.title ?? "")" ).font(.caption2)
.fontWeight(.light)
.foregroundColor(.white)
.lineLimit(1)
}
Spacer()
//Dismisses panel window
Button(action: {
dismiss()
}){
Image(systemName: "xmark")
.foregroundColor(.red)
}
}.frame(width: proxy.size.width - 100)
).padding(.horizontal, 30.0)
.frame(width: proxy.size.width , height: 60)
.foregroundColor(.black)
}
HStack{
Text("\(currentPage) / \(totalPages)")
//The button that refreshes the reader view
Button(action: {
nextChapter = mangaFeed.items[ch.chIndex + 1]
ch.chIndex += 1
Task {await reader.populate(chapterID: nextChapter!.id)}
}){
Text("next chapter")
}
}
}
}
}
struct readerOverlay_Previews: PreviewProvider {
@State static var currPage = 0
static var previews: some View {
let dummy = ChapterInfo(id: "5df4596c-febd-492e-bf0d-d98f59fd3f2b", type: "Chapter", attributes: chInfo_Attributes(volume: "1", chapter: "1", title: "Test", publishAt: "2020-05-23", externalUrl: "" ), relationships: [chapter_Relationships(id: "s", type: "manga", attributes: attributes(title: ["en":"20TH Century Boys"]))])
readerOverlay(chapter: dummy, currentPage: $currPage, totalPages: 10)
.environmentObject(FeedViewModel())
.environmentObject(ChapterIndex())
.environmentObject(ReaderViewModel())
}
}
I was following another post on here that suggested to put environment objects under the preview but that doesn't work.
Okay, so the solution was to manually set the environment object fully in the provider. Very simple solution and I just wasn't thinking clearly but I understand it now.
ReaderView Preview Code:
and ReaderOverlay