我有这个覆盖视图,当按下一个按钮时,它应该通过调用视图模型中的一个函数来刷新视图。代码在应用程序本身上工作,但在预览中不工作,我猜这是因为环境变量不包含任何数据,因为它们低于输入数据的级别。在应用程序中,数据来自FeedView,并传递给孩子。
视图结构为FeedView -> ReaderView -> ReaderOverlay。当在FeedView的预览上按下按钮时,它可以正常工作,但在ReaderView或ReaderOverlay中无法正常工作。
下面是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)
}
}
}
ReaderOverlay及其预览的代码如下:
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())
}
}
我在这里关注另一篇文章,建议将环境对象放在预览下,但这不起作用。
2条答案
按热度按时间wmtdaxz31#
好的,解决方案是在提供程序中手动设置完整的环境对象。非常简单的解决方案,我只是没有想清楚,但我现在明白了。
ReaderView预览代码:
和ReaderOverlay
knsnq2tg2#
你有太多的商店类,应该只有一个。通常有2个单例,一个用于应用程序,另一个用于充满测试数据的预览,例如。
ReaderStore
应该加载并保存您的图书模型数据。你的视图数据应该在视图结构中,而不是在视图模型对象中,这不会与SwiftUI一起飞行。我还注意到你在使用
ForEach
视图,就像它是一个数组上的for循环,这会崩溃。最好阅读有关如何使用该视图的文档。