簡體   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