导航到INCR: 3,点击导航栏返回按钮或取消按钮,你会注意到相同的视图再次被调用,但这次它是一个新版本,因为onAppear
,firstLoad = true
和rand
是不同的值。
如果你注释掉@Environment(.dismiss) var dismiss
和dismiss()
,一切都像在iOS 14中那样工作。@Environment(.presentationMode) var presentationMode
也会出现此问题。不确定这是一个bug还是我犯了一个愚蠢的错误,但这个问题导致了我的应用程序大量的问题,因为我必须能够以编程方式解散一个视图,所以任何输入将是感激的。
struct DetailView: View {
@Environment(.dismiss) var dismiss
@State var isPresenting = false
@State var incrInt = 0
@State var firstLoad = true
@State var rand = Int.random(in: 1..<500)
var body: some View {
Text("INCR: (incrInt) RAND: (rand)")
Button("NAVIGATE"){
isPresenting = true
}
Button("DISMISS"){
dismiss()
}
.onAppear(perform: {
if firstLoad{
print("ON APPEAR FIRST LOAD")
print(incrInt)
print(rand)
print("n")
firstLoad = false
}
})
NavigationLink(destination: DetailView(incrInt: (incrInt + 1)), isActive: $isPresenting){}
}
}
struct ContentView: View {
var body: some View {
NavigationView{
VStack{
DetailView()
}
}
}
}
视频链接
https://i.imgur.com/qpu7NT7.mp4
更新1:ViewModel Source of Truth
class DetailViewModel: ObservableObject {
@Published var isPresenting = false
var incr: Int
var rand = Int.random(in: 1..<500)
init(incr: Int){
self.incr = incr
print("INIT FIRST LOAD")
print(incr)
print(rand)
print("n")
}
}
struct DetailView: View {
@Environment(.dismiss) var dismiss
@StateObject var detailViewModel: DetailViewModel
var body: some View {
Text("INCR: (detailViewModel.incr) RAND: (detailViewModel.rand)")
Button("NAVIGATE"){
detailViewModel.isPresenting = true
}
Button("DISMISS"){
dismiss()
}
NavigationLink(destination: DetailView(detailViewModel: DetailViewModel(incr: (detailViewModel.incr + 1))), isActive: $detailViewModel.isPresenting){}
}
}
struct ContentView: View {
var body: some View {
NavigationView{
VStack{
DetailView(detailViewModel: DetailViewModel(incr: 0))
}
}
}
}
我通过将.navigationViewStyle(.stack)
添加到NavigationView
来解决它。我以为那是iOS上默认的导航视图样式,但也许在iOS 15中改变了。
在你的"代码,你没有使用单一的真理来源。您正在创建并将新的DetailViewModel
传递给DetailView
每次你点击NavigationLink
。只使用1个DetailViewModel,并传递它。此外,你正在改变isPresenting
,所以所有依赖于它的视图都将被更新为"new"价值。这层叠不是你想要的。修改你的逻辑。使用DetailViewModel
跨视图保持模型的状态是个好主意。试试这样做:
class DetailViewModel: ObservableObject {
// @Published var isPresenting = false // <-- not relevant
var incr: Int
var rand = Int.random(in: 1..<500)
init(incr: Int) {
self.incr = incr
print("----> DetailViewModel init --> inc: (incr) --> rand: (rand) n")
}
func doIncr(_ incr: Int) {
self.incr = incr
print("----> DetailViewModel doIncr --> inc: (incr) --> rand: (rand) n")
}
}
struct DetailView: View {
@Environment(.dismiss) var dismiss
@ObservedObject var detailViewModel: DetailViewModel
@State var showThyself = false // <--- here
var body: some View {
Text("DetailView INCR: (detailViewModel.incr) RAND: (detailViewModel.rand)")
Button("NAVIGATE"){
detailViewModel.doIncr(detailViewModel.incr + 1)
showThyself = true
}
Button("DISMISS"){
dismiss()
}
NavigationLink(destination: DetailView(detailViewModel: detailViewModel), isActive: $showThyself){}
.onAppear {
// do something with the current state of your DetailViewModel
print("----> DetailView onAppear n")
}
}
}
struct ContentView: View {
var detailViewModel = DetailViewModel(incr: 0) // <--- here
var body: some View {
NavigationView{
VStack{
DetailView(detailViewModel: detailViewModel)
}
}
}
}