繁体   English   中英

iOS 14.5 的 SwiftUI NavigationLink 不工作

[英]SwiftUI NavigationLink for iOS 14.5 not working

我在 Xcode 12.4 中有以下代码完美运行

ScrollView(.horizontal, showsIndicators: false) {
        
    LazyHGrid(rows: rows, spacing: 0) {
            
        HStack {
                        
            if (type == "Quiz") {
                        
                NavigationLink(destination: Quiz(id: quiz.id)) {
                                
                    VStack(alignment: .leading) {
                                    
                        Text("Quiz")
                            .font(.headline)
                            .foregroundColor(.white)
                            .padding(.top, 8)
                            .padding(.leading)
     
                    }
                    .background(Color.green)
                    .cornerRadius(12)
                    .shadow(color: .green, radius: 3, x: 0.0, y: 0.0)
                            
                }
                            
            } else {
                            
                NavigationLink(destination: Survey(id: survey.id)) {
                                
                    VStack(alignment: .leading) {
                                    
                        Text("Survey")
                            .font(.headline)
                            .foregroundColor(.white)
                            .padding(.top, 8)
                            .padding(.leading)
                                    
                    }
                    .background(Color.green)
                    .cornerRadius(12)
                    .shadow(color: .green, radius: 3, x: 0.0, y: 0.0)
                            
                }
                            
           } // End If
                    
           if (type == "Quiz") {
                        
               NavigationLink(destination: QuizResults(id: quiz.id)) {
                                
                   VStack(alignment: .leading) {
                            
                       Text("Quiz Results")
                           .font(.headline)
                           .foregroundColor(.white)
                           .padding(.top, 8)
                           .padding(.leading) 
                        
                   }
                   .background(Color.blue)
                   .cornerRadius(12)
                   .shadow(color: .blue, radius: 3, x: 0.0, y: 0.0)
                                
               }
                            
           } else {
                                
               NavigationLink(destination: SurveyResults(id: survey.id)) {
                                    
                   VStack(alignment: .leading) {
                                
                       Text("Survey Results")
                           .font(.headline)
                           .foregroundColor(.white)
                           .padding(.top, 8)
                           .padding(.leading)
                            
                   }
                   .background(Color.blue)
                   .cornerRadius(12)
                   .shadow(color: .blue, radius: 3, x: 0.0, y: 0.0)
                                    
              }
                                
          } 
                    
      }
      .padding([.leading, .trailing], 25)
            
}
.frame(height: 100)

我刚刚将 Xcode 更新到 12.5,以上不再起作用。

它在 12.4 中运行良好?

现在,当我单击“测验”元素时,它开始转换到显示它但立即关闭视图的测验视图,我又回到了详细视图?

有人可以看到我做错了什么,为什么现在基于 12.5 的更新停止工作?

更新

我将代码细化为最小可能的可重现形式。 似乎正在发生的事情是我有两个或更多NavigationLink的集合。

第一个是将用户导航到测验或调查的集合,if 语句将用户引导到要填写的正确视图。

12.5 中的问题是,用户可以单击 go 的第二组在第一次导航之后直接查看测验或调查的总体结果不起作用。

就像我之前所说的那样,它在 12.4 中完美运行,但似乎 12.5 不同意它。 有人可以为用户提供更好的方法来单击元素以 go 填写测验或调查或 go 查看测验或调查的结果?

我遇到了完全相同的问题,Xcode 12.4 一切正常。

https://developer.apple.com/forums/thread/677333

我尝试关注这个线程,它可能会起作用,但在某些情况下,我仍然有这个错误。

 NavigationLink(destination: EmptyView()) { EmptyView() }

显然,您可以将这 3 行代码放在 NavigationLink 附近...如果有人得到更好的答案,我将不胜感激!

多么可怕的错误。 根据我的测试和一些谷歌搜索,当视图中恰好有 2 个导航链接时会发生这种情况。 问题中的代码有 4 个,但由于 if else 语句,一次实际上只有 2 个。

我经常不知道我将拥有多少导航链接,因为这取决于用户添加了哪些数据/有多少搜索命中等。为了安全起见,我制作了一个 TripleEmptyNavigationLink 修饰符,我把它卡在了最后我的所有观点。 它正在解决弹出行为,但我仍然收到“无法呈现”警告。 很想知道是否有人有比这更好的东西!


import SwiftUI

struct TripleEmptyNavigationLink: View {
    var body: some View {
        VStack {
        NavigationLink(destination: EmptyView()) {EmptyView()}
        NavigationLink(destination: EmptyView()) {EmptyView()}
        NavigationLink(destination: EmptyView()) {EmptyView()}
            
        }
    }
}


struct TripleEmptyNavigationLinkBackground: ViewModifier {
    func body(content: Content) -> some View {
        content
            .background(TripleEmptyNavigationLink())
    }
}



extension View {
    func tripleEmptyNavigationLink()-> some View {
        self.modifier(TripleEmptyNavigationLinkBackground())
    }
}

用法:

MyView()
.tripleEmptyNavigationLink()

像 iOS 14.5.1 上的其他任何人一样,我的应用程序受到了这个可怕的错误的影响。 我在页面中有超过 3 个 NavigationLinks,我不幸运地修改了 NavigationLinks 的数量(通过添加一个虚拟 NavigationLink)来获得正确的行为。

对我来说可以的解决方法是有条件地将 NavigationLink 添加到视图中。

代替:

var body: some View {
  NavigationLink(destination: AnotherView(), isActive: $someCondition) { EmptyView() }
}

我有这个:

var body: some View {
  if someCondition {
    NavigationLink(destination: AnotherView(), isActive: $someCondition) { EmptyView() }
  }
}

行为并不完全相同,因为您丢失了一些导航 animation 糖果,但至少您再次拥有一个工作应用程序,并且修复相对容易理解。

您也可以仅将其短路到 14.5,并在其他地方正常行为:

  /// Assumes this gets fixed by Apple until 14.6 is out
  var onIOS14_5: Bool {
    let systemVersion = UIDevice.current.systemVersion
    return systemVersion.starts(with: "14.5")
  }

  var body: some View {

  if !onIOS14_5 || someCondition {
    NavigationLink(destination: AnotherView(), isActive: $someCondition) { EmptyView() }
  }
}

也许这对某人有所帮助,并让所有人都希望苹果能够修复这个令人尴尬的错误。 现在我想要我的半天回来。

添加带有空视图的 NavigationLink 对我不起作用。 我解决了我的问题,从 ForEach 中删除了所有NavigationLink并使用一个来控制导航到详细视图、点击手势和 2 个 state 变量来跟踪正在点击的内容。

可以在 Paul Hudson 的网站上找到示例损坏的代码和修复。

https://www.hackingwithswift.com/forums/swiftui/unable-to-present-please-file-a-bug/7901/8237

以下是完整的工作版本

import SwiftUI

struct NavigationViewOptions {
    enum OptionType { case main, optional }
    typealias Option = (id: UUID, value: String, type: Self.OptionType)
    static var options: [Option] = [
        (UUID(), "Option 1", .main),
        (UUID(), "Option 2", .optional),
        (UUID(), "Option 3", .main),
        (UUID(), "Option 4", .main),
        (UUID(), "Option 5", .optional),
    ]
        
    static func buildView(for option: Option) -> some View {
        switch option.type {
        case .main:
            return Text("Main Option selected\n\(option.value)").font(.title).fontWeight(.bold)
        case .optional:
            return Text("Optional Option selected\n\(option.value)").font(.title3).italic().fontWeight(.medium)
        }
    }
}

struct NavigationViewWorking: View {

    // State variables to leep track of what option has been tapped on and when to navigate to new view
    @State private var selectedOption: NavigationViewOptions.Option = (id:UUID(),"",.main)
    @State private var showDetail: Bool = false
    
    var body: some View {
        NavigationView {
            ScrollView{
                VStack (alignment:.leading) {
                    Text("NAVIGATION FIX FOR:\nUnable to present. Please file a bug.")
                        .padding(.bottom, 40)

                    ForEach(NavigationViewOptions.options, id: \.id) { option in
                        Text(option.value)
                            .font(.title)
                            .padding(.vertical, 10)
                            .foregroundColor(.accentColor) // same color as navigationLink
                            // handle tap on option
                            .onTapGesture {
                                selectedOption = option
                                showDetail = true
                            }
                    }
                    Spacer()
                    NavigationLink("", destination: NavigationViewOptions.buildView(for: selectedOption), isActive: $showDetail)
                        .opacity(0)
                }
                .navigationTitle("Options")
            }
            // INITIAL DETAIL VIEW
            Text("Select option from the left")
        }
    }
}

在 Xcode13 beta 中仍然存在这个问题。

到目前为止的解决方案:

1、用列表或表单包裹 NavigationLink:

    List {
        NavigationLink(destination: Text("1")) {
            Text("1")
        }
        NavigationLink(destination: Text("2")) {
            Text("2")
        }
        NavigationLink(destination: Text("3")) {
            Text("3")
        }
    }

2、或者使用一个NavigationLink,并从func创建目标视图:

struct TaskIndexPage: View {
    
    func buildView() -> some View {
        // return you destination
        switch self.option {
        case 1:
            return Text("\(option)")
        default:
            return Text("\(option)")
        }
    }
    
    @State private var showDetail: Bool = false

    @State private var option: Int = 0

    var body: some View {

        VStack {
            Button {
                showDetail = true
                option = 1
            } label: { Text("button 1") }
            Button {
                showDetail = true
                option = 2
            } label: { Text("button 2") }
            Button {
                showDetail = true
                option = 3
            } label: { Text("button 3") }
        }
        // handle navigating
        NavigationLink(destination: self.buildView(), isActive: $showDetail) {}.opacity(0)
        
    }
}

我遇到了完全相同的问题。

我的代码:

class NavigationManager: ObservableObject {
    
    static let shared: NavigationManager = {
        return NavigationManager()
    }()
    
    @Published var showingMain: Bool
    @Published var showingSub: Bool
    @Published var content: AnyView

    init() {
        showingMain = false
        showingSub = false
        content = AnyView(EmptyView())
    }
    
    func forward<T:View>(content: @escaping () -> T ) {
        showView()
        self.content = AnyView(content())
    }
    
    private func showView() {
        if !showingMain,!showingSub {
            showingMain = true
        } else if showingMain,!showingSub {
            showingSub = true
        } else if !showingMain,showingSub {
            showingMain = true
        }
    }
}
struct NavigationLinkGroup: View {
    @EnvironmentObject var navigationManager: NavigationManager
    
    var body: some View {
        Group {
            NavigationLink(destination: navigationManager.content, isActive: $navigationManager.showingMain) {EmptyView()}
            
            NavigationLink(destination: navigationManager.content, isActive: $navigationManager.showingSub) {EmptyView()}
        }
    }
}
struct ContentView: View {
    var body: some View {
        NavigationView {
            NavigationLinkGroup()
        }
    }
}

https://github.com/Ftrybe/CustomBackButtonOfSwiftUIApp/tree/master/CustomBackButtonOfSwiftUI

如果 NavigationView 中的 NavigationLink 不止一个,那么这个 bug 就会被归档。

这是我的解决方案。

import SwiftUI

enum MyLink {
    case myView1
    case myView2
}

struct MyView1: View {
    var body: some View {
        Text("MyView1")
    }
}

struct MyView2: View {
    var body: some View {
        Text("MyView2")
    }
}

struct ExampleView: View {
    @State var currentLink: MyLink = .myView1
    @State var isLinkViewShow: Bool = false
    
    func getLinkView(_ myLink: MyLink) -> some View {
        if myLink == .myView1 {
            return AnyView(MyView1())
        } else {
            return AnyView(MyView2())
        }
    }
    
    var body: some View {
        NavigationView {
            VStack {
                NavigationLink("", 
                               destination: getLinkView(currentLink), 
                               isActive: $isLinkViewShow)
                
                // Press to navigate to MyView1
                Button(action: {
                    currentLink = .myView1
                    isLinkViewShow = true
                }) {
                    Text("To MyView1")
                }
                
                // Press to navigate to MyView2
                Button(action: {
                    currentLink = .myView2
                    isLinkViewShow = true
                }) {
                    Text("To MyView2")
                }
            }
        }
    }
}

如果我包含此 edgesIgnoringSafeArea 或 ignoresSafeArea,它将停止工作

添加延迟会使自动导航再次工作。

NavigationLink(destination: PopupView(),isActive: $showView){}

&

.onAppear {
if (test()){
    DispatchQueue.main.asyncAfter(deadline: .now() + 1) {showView = true}
    }
}

对我来说,正确的答案没有用。 它显示Unable to present -message,然后需要的视图被快速推送并弹出回来。 在玩耍时,我找到了一个可行的解决方案。 我将没有labelNotificationLink设置为普通List项。

NavigationView {
  ZStack {
    List {
      NavigationLink(isActive: $isFirstViewPresented,
                     destination: firstView,
                     label: EmptyView.init)
      NavigationLink(isActive: $isSecondViewPresented,
                     destination: secondView,
                     label: EmptyView.init)
    }
    .listStyle(.plain)
    //...
    Button("Show first view") { isFirstViewPresented.toggle() }
    Button("Show second view") { isSecondViewPresented.toggle() }
  }
}

不要忘记用@State包装活动属性。

对我来说它也有一些好处(所有导航链接都放在view -getter 的顶部,我不需要通过所有代码查找它。

对于这个可怕的错误,我永远找不到可靠的解决方案。 所以我决定创建一个自定义 NavigationLink,使用Introspect ( https://github.com/siteline/SwiftUI-Introspect )。 这比预期的要好得多,因为所有 swiftui 相关功能继续照常工作。 似乎该错误专门针对 NavigationLink。

private struct NavigationLinkImpl<Destination: View, Label: View>: View {
    let destination: () -> Destination?
    @State var isActive = false
    @ViewBuilder let label: () -> Label

    var body: some View {
        NavigationLinkImpl1(destination: destination, isActive: $isActive, label: label)
    }
}

private struct NavigationLinkImpl1<Destination: View, Label: View>: View {
    let destination: () -> Destination
    @Binding var isActive: Bool
    @ViewBuilder let label: () -> Label
    @State var model = Model()

    var body: some View {
        Button(action: action, label: label)
            .introspectNavigationController(customize: handle)
            .id(isActive)
    }

    func handle(nav: UINavigationController) {
        if isActive {
            if model.destination == nil {
                let dest = UIHostingController<Destination>(rootView: destination())
                nav.pushViewController(dest, animated: true)
                model.destination = dest
            }
        } else {
            if let dest = model.destination {
                if let i = nav.viewControllers.lastIndex(of: dest) {
                    nav.setViewControllers(.init(nav.viewControllers.prefix(i + 1)), animated: true)
                }
                model.destination = nil
            }
        }
        if isActive != model.contains(nav: nav) { // detect pop
            isActive = model.contains(nav: nav)
        }
    }

    final class Model {
        var destination: UIHostingController<Destination>?
        func contains(nav: UINavigationController) -> Bool { destination.map { nav.viewControllers.contains($0) } ?? false }
    }

    func action() { isActive = true }
}

extension NavigationLink {
    init<Destination: View, Label: View>(destination: @autoclosure @escaping () -> Destination, @ViewBuilder label: @escaping () -> Label) {
        self.init(body: NavigationLinkImpl(destination: destination, label: label))
    }

    init<Destination: View, Label: View>(destination: @autoclosure @escaping () -> Destination, isActive: Binding<Bool>, @ViewBuilder label: @escaping () -> Label) {
        self.init(body: NavigationLinkImpl1(destination: destination, isActive: isActive, label: label))
    }

    init<Destination: View>(_ text: String, destination: @autoclosure @escaping () -> Destination, isActive: Binding<Bool>) {
        self.init(destination: destination(), isActive: isActive) { Text(text) }
    }

    init<Destination: View>(_ text: String, destination: @autoclosure @escaping () -> Destination) {
        self.init(destination: destination()) { Text(text) }
    }
}

把它放在一个文件中,你现有的 NavigationLinks 就可以正常工作了。 在 ios 14 和 15 中测试

就我而言,NavigationLink 不起作用,因为我添加了 an.onTapGesture 来关闭键盘。

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM