SwiftUI 上的 NavigationLink 两次推送视图

Posted

技术标签:

【中文标题】SwiftUI 上的 NavigationLink 两次推送视图【英文标题】:NavigationLink on SwiftUI pushes view twice 【发布时间】:2020-01-16 15:53:33 【问题描述】:

在 SwiftUI 中添加 NavigationLink 时,目的地会出现两次,例如:我点击 NavigationLink 并推送我的目的地,但是当我通过后退按钮或滑动手势关闭目的地时,它会再次推送目的地而不点击链接。 这是我处理链接的代码部分:

var body: some View 
    HStack(spacing: 8.0) 
        ForEach(part.getReference())  (imageRef: ReferenceImage) in
            ZStack(alignment: .topTrailing) 
                Image(uiImage: imageRef.getUIImage())
                .resizable()
                .frame(width: 90, height: 90)
                .cornerRadius(6)
                .onLongPressGesture 
                    print("looong")
                    self.managedObjectContext.delete(imageRef)
                    do 
                        try self.managedObjectContext.save()
                     catch 
                        print("error deleting: \(error.localizedDescription)")
                    
                
                ZStack(alignment: .center) 
                    Circle()
                        .foregroundColor(Color.appColors.lightRose)
                        .opacity(0.7)
                        .frame(width: 35, height: 35)
                    Image(systemName: "arkit")
                        .imageScale(.large)
                
                NavigationLink(destination:
                    ZStack 
                        Color.appColors.rose
                            .edgesIgnoringSafeArea(.top)
                        ReferenceARSwiftUIView(currentImage: imageRef.getUIImage())
                            .navigationBarTitle("AR Reference")
                    

                ) 
                    EmptyView()
                    .frame(width: 90, height: 90)
                

            
        .animation(.interpolatingSpring(stiffness: 0.5, damping: 0.5))

编辑 01: 正如建议的那样,我删除了代码中的一些噪音:

var part: Part
var body: some View 
    HStack(spacing: 8.0) 
        ForEach(part.getReference())  (imageRef: ReferenceImage) in
            ZStack(alignment: .topTrailing) 
                Image(uiImage: imageRef.getUIImage())
                .resizable()
                .frame(width: 90, height: 90)
                .cornerRadius(6)
                NavigationLink(destination: ReferenceARSwiftUIView(currentImage: imageRef.getUIImage())) 
                    EmptyView()
                    .frame(width: 90, height: 90)
                

            
        .animation(.interpolatingSpring(stiffness: 0.5, damping: 0.5))

编辑 02: 我想我缩小了范围,基本上如果我删除 ForEach,NavigationLink 会正确推送到下一个视图。此外,根据我在 ForEach 数组中的项目数量,推送的数量是相同的。

【问题讨论】:

您是否有机会在您的代码中删除和/或添加内容以便我们复制您的问题?您有几件事(Color.appColors.lightRoseImage、不需要的堆栈)确实会增加噪音。也许如果您将其剥离为 NavigationViewNavigationLink也许 ForEach 让我们复制您的问题,您可能会发现它正在工作......此时您可以添加回到其余部分,看看为什么您发布的代码不是。 好吧,我认为已经消除了代码中的大部分噪音?? 我可能已经缩小了问题的范围,我在编辑 02 上解释了 谢谢,希望我没有冒犯你。两个想法。 (1) 我很少看到没有ListForEach。这会有帮助吗? hackingwithswift.com/quick-start/swiftui/… 更多,(2)我积极检查这个网站的 SwiftUI 标签。我记得关于循环中ListNavigationLink(甚至Button)行为的几个问题。你在这个网站上搜索过那些吗?事实是,我停止使用 NavigationViewList 的组合,因为...原始... SwiftUI 与 UIKit 相比, 我遇到了同样的问题。我相信在 ForEach 中使用 NavigationLink 时,SwiftUI 中可能存在错误。我无法让它与ScrollView 一起工作,如下所示。如果我不使用 ForEach,我只能让它工作。 【参考方案1】:

我确定Part 符合Identifiable 协议并具有id 属性。

NavigationLink 的目标被多次显示,因为在forEach 循环中有多个Part 实例具有完全相同的标识id

只要确保Part 的每个实例都有一个唯一的id,一切都会按预期工作。

【讨论】:

hackingwithswift.com/books/ios-swiftui/…【参考方案2】:

我通过将 NavigationLink 的标签设置为模型项的唯一 id 解决了这个问题。

假设你的 imageRef 有一个 ID,ReferenceImage 类。

var part: Part
var body: some View 
    HStack(spacing: 8.0) 
        ForEach(part.getReference())  (imageRef: ReferenceImage) in
            ZStack(alignment: .topTrailing) 
                Image(uiImage: imageRef.getUIImage())
                .resizable()
                .frame(width: 90, height: 90)
                .cornerRadius(6)
                NavigationLink(destination: ReferenceARSwiftUIView(currentImage: imageRef.getUIImage()), tag: imageRef.id) 
                    EmptyView()
                    .frame(width: 90, height: 90)
                

            
        .animation(.interpolatingSpring(stiffness: 0.5, damping: 0.5))
NavigationLink(destination: ReferenceARSwiftUIView(currentImage: imageRef.getUIImage()), tag: imageRef.id)

【讨论】:

【参考方案3】:

是的,将 List 更改为 ScrollView 在类似的情况下帮助了我。


                    ScrollView 
                        if !usersViewModel.isLoading 
                            ForEach(self.usersViewModel.users, id: \.id)  user in
                                NavigationLink(destination: UserDashboardView(showDashboardDetail: $showDashboardDetail, user: user)) 
                                    VStack(alignment: .leading) 
                                        NetworkCardView(user: user)
                                    
                                    .frame(width: screen.size.width - 60, height: 250)
                                    .padding(.top)
                                
                            
                            .listRowBackground(AppColor())
                        
                    

【讨论】:

【参考方案4】:

我无法重现您的问题,因为即使是精简版也包含您声明的类型,但未包含在问题中。

有几点:

如果要使用NavigationLink,则需要将视图嵌入NavigationView

如果您在HStack 中使用ForEach,则可能会用完显示所有元素的空间,因此最好将其包装在ScrollView 中。

最后但同样重要的是:在ForEach 中,您必须将NavigationLink 设为您的***视图,并将任何其他视图设为其内容:

var body: some View 
        NavigationView 
           ScrollView(.horizontal) 
                HStack 
                    ForEach(part.getReference())  (imageRef: ReferenceImage) in
                        NavigationLink(destination: ReferenceARSwiftUIView(currentImage: imageRef.getUIImage())) 
                            Image(uiImage: imageRef.getUIImage())
                                .resizable()
                                .frame(width: 90, height: 90)
                                .cornerRadius(6)
                        
                    
               
            
        
    

【讨论】:

以上是关于SwiftUI 上的 NavigationLink 两次推送视图的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI NavigationLink 如何到达另一个 SwiftUI 页面?

NavigationLink 中的 SwiftUI 按钮

SwiftUI:NavigationLink 奇怪的行为

SwiftUI:NavigationLink 内的水平 ScrollView 会中断导航

有没有办法向 NavigationLink 添加额外的功能? SwiftUI

无法单击列表中的 NavigationLink (SwiftUI)