我在第一个屏幕上有List个ID和分数.

在详细信息屏幕中,我单击并调用一个回调,该回调将分数添加到List.

当我对列表顶部的项目执行此操作时,什么都没有发生.(好)

当我对列表底部的项目执行此操作时,导航视图弹出Backback并将我放回第一页.(坏)

import SwiftUI

class IdAndScoreItem {
    var id: Int
    var score: Int
    init(id: Int, score: Int) {
        self.id = id
        self.score = score
    }
}

@main
struct CrazyBackStackProblemApp: App {
    var body: some Scene {
        WindowGroup {
            NavigationView {
                ListView()

            }
            .navigationViewStyle(.stack)
        }
    }
}

struct ListView: View {
    @State var items = (1...50).map { IdAndScoreItem(id: $0, score: 0) }
    func addScoreAndSort(item: IdAndScoreItem) {
        items = items
            .map {
                if($0.id == item.id) { $0.score += 1 }
                return $0
            }
            .sorted {
                $0.score > $1.score
            }
    }
    var body: some View {
        List(items, id: \.id) { item in
            NavigationLink {
                ScoreClickerView(
                    onClick: { addScoreAndSort(item: item) }
                )
            } label: {
                Text("id: \(item.id) score:\(item.score)")
            }
        }
    }
}

struct ScoreClickerView: View {
    var onClick: () -> Void
    var body: some View {
        Text("tap me to increase the score")
            .onTapGesture {
                onClick()
            }
    }
}

我怎样才能在细节页面上重新排序列表,这会反映在列表页面上,但导航堆栈不会弹出(当我在列表底部的列表项上执行时).我试着加了navigationStyle(.stack)也没用.

谢谢你的帮助!

推荐答案

Resort更改ID生成列表的顺序,重新创建导致当前导航链接被 destruct 的内容,因此返回导航.

一种可能的解决方案是将链接与内容分离——可以通过引入类似 Select (点击行)的内容,并通过该 Select 激活一个导航链接来实现.

使用Xcode 14/iOS 16测试

demo

@State private var selectedItem: IdAndScoreItem?  // selection !!

var isNavigate: Binding<Bool> {   // link activator !!
    Binding(get: { selectedItem != nil}, set: { _ in selectedItem = nil })
}

var body: some View {
    List(items, id: \.id) { item in
        Text("id: \(item.id) score:\(item.score)")   // tappable row
            .frame(maxWidth: .infinity, alignment: .leading)
            .contentShape(Rectangle())
            .onTapGesture {
                selectedItem = item
            }
    }
    .background(
        NavigationLink(isActive: isNavigate) {  // one link !!
            ScoreClickerView {
                if let item = selectedItem {
                    addScoreAndSort(item: item)
                }
            }
        } label: {
            EmptyView()
        }
    )
}

Swift相关问答推荐

TabView中的视频播放器意外播放

日期格式yyyyyy—MM—dd hh:mm:ss +0000到dd MMM,以swift格式表示""""

Swift concurrency reload/await,支持只执行成功并重试

当计数大于索引时,索引超出范围崩溃

Swift中从头开始的基本HTTP客户端

如何在设备(或常量)地址空间中创建缓冲区?

本地对象的异步/等待引用捕获总是安全的还是理论上不安全?

在 RealmSwift 中表示范围值?

在领域 SwiftUI 异常中使用 Apple 登录:无法识别的 Select 器发送到实例

Swift-SceneKit-无法从art.scnassets加载.scn文件

如何在不提交到应用store 的情况下在本地运行我的应用

如何打印出此 struct 中的数据?

为 ObservedObject 和 State 对象配置预览

我将哪种 Swift 数据类型用于货币

SwiftUI 中的 .primary 和 .secondary colored颜色 是什么?

在 UItextfield 的右视图上添加一个按钮,文本不应与按钮重叠

Swift :如何在一组字符之后得到所有东西

使用 ARAnchor 插入 node 和直接插入 node 有什么区别?

如何快速格式化用户显示(社交网络等)的时间间隔?

ld:入口点(_main)未定义.对于架构 x86_64:Xcode 9