SwiftUIで以前にクリックしたNavigationLinkに再度アクセスしようとすると、NavigationLinkがフリーズする


10

JSONデータを取得し、取得したアイテムのリストをFileBrowserタイプのビューに表示する機能を含むアプリを設計しています。このビューでは、ユーザーはフォルダーをクリックしてファイルツリーの詳細を表示したり、ファイルをクリックしてそのファイルに関するメタデータを表示したりできる必要があります。

これが機能しているときに、ファイルまたはフォルダーをクリックして戻ってもう一度クリックすると、NavigationLinkがトリガーされず、別のNavigationLinkをクリックするまでビューに止まっていることがわかりました。

これは、この問題を示すgifです。

ダブルタップバグ

ここに示されているように、BlahBlahをクリックすると、NavigationLinkがアクティブになり、BlahBlahに移動します。その後、戻ってBlahBlahに移動しようとすると、灰色になり、クリックしたことが登録されますが、そこに移動することはありません。 。TestFileをクリックするとこれが修正され、BlahBlahに戻ることができます。

リスト項目は、次の構造体で作成されています

private struct FileCell{
    var FileName: String
    var FileType: String
    var FileID: String = ""
    var isContainer: Bool
}

private struct constructedCell: View{

    var FileType: String
    var FileName: String
    var FileID: String

    var body: some View {
        return
            HStack{
                VStack(alignment: .center){
                    Image(systemName: getImage(FileType: FileType)).font(.title).frame(width: 50)
                }
                Divider()
                VStack(alignment: .leading){
                    Text(FileName).font(.headline)
                        .multilineTextAlignment(.leading)
                    Text(FileID)
                        .font(.caption)
                        .multilineTextAlignment(.leading)
                }
        }
    }
}

次のように、navigationLinksでビューに呼び出されます

List(cellArray, id: \.FileID) { cell in
                if (cell.isContainer) {
                    NavigationLink(destination: FileView(path: "/\(cell.FileID)", displaysLogin: self.$displaysLogin).navigationBarTitle(cell.FileName)){
                        constructedCell(FileType: cell.FileType, FileName: cell.FileName, FileID: cell.FileID)
                    }
                } else {
                    NavigationLink(destination: DetailView(FileID: cell.FileID).navigationBarTitle(cell.FileName)){
                        constructedCell(FileType: cell.FileType, FileName: cell.FileName, FileID: cell.FileID)
                    }
                }
            }

私のNavigationViewは上記のビューで初期化されています(アプリにはタブビューがあります)これは次のようになります

TabView(selection: $selection){
               NavigationView{
                    FileView(displaysLogin: self.$displaysLogin)
                        .navigationBarTitle("Home", displayMode: .inline)
                        .background(NavigationConfigurator { nc in
                            nc.navigationBar.barTintColor = UIColor.white
                            nc.navigationBar.titleTextAttributes = [.foregroundColor : UIColor.black]
                        })
                }
                .font(.title)
                .tabItem {
                    VStack {
                        Image(systemName: "folder.fill")
                        Text("Files")
                    }
                }
                .tag(0)
}

NavigationConfiguratorは、navigationBarの色を処理するために使用する構造体です。こんな感じで設置

struct NavigationConfigurator: UIViewControllerRepresentable {
    var configure: (UINavigationController) -> Void = { _ in }

    func makeUIViewController(context: UIViewControllerRepresentableContext<NavigationConfigurator>) -> UIViewController {
        UIViewController()
    }
    func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<NavigationConfigurator>) {
        if let nc = uiViewController.navigationController {
            self.configure(nc)
        }
    }

}

私のNavigationConfiguratorがこれを引き起こしているとは思いませんか?このバグは、アプリ内の他のnavigationLinksでも発生しますが、ここでFileBrowserビューで示すのが最も簡単でした。

これはSwiftUIのバグですか?もしそうなら、誰かがこれを回避する方法を知っていますか?そうでない場合、私は何を間違っていますか?


よくわかりません。しかし、あなたがラップしてはならないNavigationLinkの内側NavigationViewと削除NavigationViewからFileView?私はこのようにそれを行ういくつかの例を見ました。
Giovanni、

@GiovanniTerlingen私があなたの言っていることを誤解しない限り、これは私がやっていることです。NavigationLink内側にあるFileViewに包まれているNavigationView、したがってNavigationLinkのラップされ内部NavigationView
Vapidant

最低限実行可能なプロジェクトを提供してください。これは再現できないので、おそらくSwiftUIのバグではありません。
Mojtaba Hosseini、

完全なソースコードを提供して問題を解決できるか
Hardik Bar

どのように準備しましたcellArrayか?
E.Coms

回答:


5

同じ問題がありました-これを試してください。私はこれをハックと呼び、swiftUIのバグが修正されたら削除します。

struct ListView: View {
@State private var destID = 0
...
var body: some View {
...
  NavigationLink(destination: FileView(path: "/\(cell.FileID)", displaysLogin: self.$displaysLogin)
   .navigationBarTitle(cell.FileName) 
   .onDisappear() { self.destID = self.destID + 1 }
  ){
   constructedCell(FileType: cell.FileType, FileName: cell.FileName, FileID: cell.FileID) 
  }.id(destID)

基本的に、一部の状況(iOS 13.3-シミュレータ?)では、宛先ビューがナビゲーションスタックから削除されても、NavigationLinkがリセットされないようです。回避策として、ナビゲーションリンクを再生成する必要があります。これは、IDを変更することによって行われます。これは私の問題を修正しました。

ただし、チェーンされているNavigationLinks(リンクの別のリストにつながるリンク)がある場合、このソリューションは副作用を引き起こします。スタックは、最後のビューを表示する2回目の試行で原点に戻ります。


このバグは最新のIOSバージョンで修正されています。現状の問題を解決したので、これを正解としてマークしましたが、これは問題ではありません。問題の説明も好きです。ありがとうございました。
Vapidant

最新のiOSバージョンとは、13.4またはベータ版を意味しますか?
Ricardo Alves

私も知りたいです。どのバージョンが正しく動作しますか?私は13.3(現在最新のiOSです)を使用していますが、問題はまだ残っています。
マロー

私はこのバグは、IOS 13.3のベータビルドで提示されたが、IOS 13.3ベータ4のように固定されていると信じて
Vapidant
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.