如何强制列表通过另一个视图的切换按钮重绘?

How to force List to redraw by another View's toggle Button?

我从 Google Sheet 中获取了 JSON 数据并使用 ForEach 填充到一个列表中。我使用位于另一个视图中的结构 HeaderView 并放置一个按钮作为切换。但是,即使我使用@State ascd 变量,当我按下切换按钮时,列表也不会重绘。

下面是我的一些代码,有什么我遗漏的吗?

struct HeaderView: View {
    // @State var asc: Bool = true
    var holding: String = "持倉"
    var earning: String = "賺蝕"
    // @State var tog_value: Bool = ContentView().ascd

    var body: some View {
        HStack {
            Button(action: {
                ContentView().ascd.toggle()
            }
            ) {
                Text("Button")
            }
            Text(holding)
            Text(earning)
        }
    }
}
struct ContentView: View {
    @ObservedObject var viewModel = ContentViewModel()
    @ObservedObject var viewModelTotal = ContentViewModelTotal()
    @State var ascd: Bool = false
    var totalss = ContentViewModelTotal.fetchDatasTotal
    var body: some View {
        List {
            Section(header: HeaderView()) {
                ForEach(viewModel.rows, id: \.stockname) { rows in
                    // Text(user.stock_name)
                    ListRow(name: rows.stockname, code: rows.stockcode, cur_price: rows.currentprice, mkt_value: rows.marketvalue, amnt: rows.amount, avg_cost: rows.averagecost, pft: rows.profit, pft_pcnt: rows.profitpercent)
                }
            }
            .onAppear {
                self.viewModel.fetchDatas()
                self.ascd.toggle()
                if self.ascd {
                    self.viewModel.rows.sort { [=11=].stockname < .stockname }
                } else {
                    self.viewModel.rows.sort { [=11=].stockname > .stockname }
                }
            }
        }
    }
}

要更改另一个视图的变量,您可以使用 @Binding 变量:

struct HeaderView: View {
    ...

    @Binding var ascd: Bool

    var body: some View {
        HStack {
            Button(action: {
                self.ascd.toggle()
            }) {
                Text("Button")
            }
            Text(holding)
            Text(earning)
        }
    }
}

我建议将排序逻辑移至您的 ViewModel

class ContentViewModel: ObservableObject {
    @Published var ascd: Bool = false {
        didSet {
            if ascd {
                rows.sort { [=11=].hashValue < .hashValue }
            } else {
                rows.sort { [=11=].hashValue > .hashValue }
            }
        }
    }

    ...
}

如果它在ContentView中的.onAppear中,它只会在您的View显示在屏幕上时执行。

并且您必须使用 ViewModel 的 ascd 变量初始化 HeaderView

HeaderView(ascd: $viewModel.ascd)