简体   繁体   English

SwiftUI NavigationLink push in onAppear 使用@ObservableObject 时立即弹出视图

[英]SwiftUI NavigationLink push in onAppear immediately pops the view when using @ObservableObject

I want to programmatically be able to navigate to a link within a List of NavigationLinks when the view appears (building deep linking from push notification).当视图出现时,我希望能够以编程方式导航到NavigationLinks List中的链接(从推送通知构建深度链接)。 I have a string -> Bool dictionary which is bound to a custom Binding<Bool> inside my view.我有一个字符串 -> Bool 字典,它绑定到我的视图中的自定义Binding<Bool> When the view appears, I set the bool property, navigation happens, however, it immediately pops back.当视图出现时,我设置 bool 属性,导航发生,但是,它立即弹回。 I followed the answer in SwiftUI NavigationLink immediately navigates back and made sure that each item in the List has a unique identifier, but the issue still persists.我按照SwiftUI NavigationLink 中的答案立即返回并确保List中的每个项目都有一个唯一标识符,但问题仍然存在。

Two questions:两个问题:

  1. Is my binding logic here correct?我的绑定逻辑在这里正确吗?
  2. How come the view pops back immediately?视图怎么会立即弹回来?
import SwiftUI

class ContentViewModel: ObservableObject {
    @Published var isLinkActive:[String: Bool] = [:]
}

struct ContentViewTwo: View {
    @ObservedObject var contentViewModel = ContentViewModel()
    @State var data = ["1", "2", "3"]
    @State var shouldPushPage3: Bool = true

    var page3: some View {
        Text("Page 3")
            .onAppear() {
                print("Page 3 Appeared!")
        }
    }

    func binding(chatId: String) -> Binding<Bool> {
        return .init(get: { () -> Bool in
            return self.contentViewModel.isLinkActive[chatId, default: false]
        }) { (value) in
            self.contentViewModel.isLinkActive[chatId] = value
        }
    }

    var body: some View {
        return
            List(data, id: \.self) { data in
                NavigationLink(destination: self.page3, isActive: self.binding(chatId: data)) {
                    Text("Page 3 Link with Data: \(data)")
                }.onAppear() {
                    print("link appeared")
                }
            }.onAppear() {
                print ("ContentViewTwo Appeared")
                if (self.shouldPushPage3) {
                    self.shouldPushPage3 = false
                    self.contentViewModel.isLinkActive["3"] = true
                    print("Activating link to page 3")
                }
        }
    }
}

struct ContentView: View {
    var body: some View {
        return NavigationView() {
            VStack {
                Text("Page 1")
                NavigationLink(destination: ContentViewTwo()) {
                    Text("Page 2 Link")
                }
            }
        }
    }
}

The error is due to the lifecycle of the ViewModel, and is a limitation with SwiftUI NavigationLink itself at the moment, will have to wait to see if Apple updates the pending issues in the next release.该错误是由于 ViewModel 的生命周期造成的,并且目前是 SwiftUI NavigationLink 本身的限制,必须等待 Apple 是否在下一个版本中更新未决问题。

Update for SwiftUI 2.0 : SwiftUI 2.0更新:

Change:改变:

@ObservedObject var contentViewModel = ContentViewModel()

to:至:

@StateObject var contentViewModel = ContentViewModel()

@StateObject means that changes in the state of the view model do not trigger a redraw of the whole body . @StateObject表示视图 model 的 state 中的更改不会触发整个body的重绘。

You also need to store the shouldPushPage3 variable outside the View as the view will get recreated every time you pop back to the root View .您还需要将shouldPushPage3变量存储在View之外,因为每次弹回根View时都会重新创建视图。

enum DeepLinking {
    static var shouldPushPage3 = true
}

And reference it as follows:并参考如下:

if (DeepLinking.shouldPushPage3) {
    DeepLinking.shouldPushPage3 = false
    self.contentViewModel.isLinkActive["3"] = true
    print("Activating link to page 3")
}

The bug got fixed with the latest SwiftUI release .最新的 SwiftUI 版本修复了该错误。 But to use this code at the moment, you will need to use the beta version of Xcode and iOS 14 - it will be live in a month or so with the next GM Xcode release.但目前要使用此代码,您将需要使用 Xcode 和 iOS 14 的 beta 版本 - 它将在下一个 GM ZA3B5EBD8A1E9EBF44A3ZA172E80D5A7D3 发布一个月左右。

I was coming up against this problem, with a standard (not using 'isActive') NavigationLink - for me the problem turned out to be the use of the view modifiers: .onAppear{code} and.onDisappear{code} in the destination view .我遇到了这个问题,使用标准(不使用'isActive')NavigationLink - 对我来说,问题原来是使用视图修饰符:目标视图中的.onAppear{code}和.onDisappear{code} . I think it was causing a re-draw loop or something which caused the view to pop back to my list view (after approx 1 second).我认为它导致了重新绘制循环或导致视图弹回我的列表视图(大约 1 秒后)。 I solved it by moving the modifiers onto a part of the destination view that's not affected by the code in those modifiers.我通过将修饰符移动到不受这些修饰符中的代码影响的目标视图的一部分来解决它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 SwiftUI:如果在 ForEach 中使用,NavigationLink 会立即弹出 - SwiftUI: NavigationLink pops immediately if used within ForEach 如何在没有 NavigationLink 的情况下使用 SwiftUI 推送新的根视图? - How to push a new root view using SwiftUI without NavigationLink? SwiftUI 意外 NavigationLink 自动弹出 - SwiftUI Unexpectedly NavigationLink pops automatically 在SwiftUI中继承ObservableObject时不会触发视图刷新 - View refreshing not triggered when ObservableObject is inherited in SwiftUI SwiftUI 在新工作表的视图中使用 ObservableObject - SwiftUI Using ObservableObject in View on New Sheet SwiftUI NavigationLink 立即加载目标视图,无需单击 - SwiftUI NavigationLink loads destination view immediately, without clicking SwiftUI NavigationLink 导致推送发生,然后在完成后弹出,然后再次推送 - SwiftUI NavigationLink causes a push to happen, then it pops after completion, then pushes again for good SwiftUI NavigationLink 会自动弹出,这是出乎意料的 - SwiftUI NavigationLink pops automatically which is unexpected 显示键盘时,Form 中的 SwiftUI Picker 会立即弹回 - SwiftUI Picker in Form pops back immediately when keyboard is showing 我无法在 SwiftUI 中使用.onAppear()、.onTapGesture() 函数和 NavigationLink 更改值 - I can not change the value with .onAppear(), .onTapGesture() function and with a NavigationLink in SwiftUI
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM