如何在SwiftUI中从详细信息视图编辑列表视图

时间:2019-12-09 07:21:25

标签: swift swiftui swiftui-list

我正在寻找一种从详细信息视图编辑列表数据的解决方案。在HomeVC中,我有一个列表,在此列表中,我传递了详细数据和一个用于更新此列表的函数。但这会出错:

class HomeViewModel: ObservableObject {
    @Published var vouchers: [Voucher] = []
    func fetchVouchers () {
        let request = APIEndpoint.getHomeVouchers()
        URLSession.shared.dataTask(with: request) { (data, response, err) in
            guard let data = data else { return }
            let resData = try! JSONDecoder().decode(VouchersResponse.self, from: data)
            DispatchQueue.main.async {
                self.vouchers = resData.data.promotions
            }
        }.resume()
    }
}

struct HomeVC: View {

    @ObservedObject var VM = HomeViewModel()

    var body: some View {
        List {
           ForEach (VM.vouchers) { voucher in
                ModalLink (destination: VoucherDetailView(voucher: voucher, didEditVoucher: { v in
                    self.VM.vouchers.first(where: { $0.id == v.id })?.purchased = true
                })) {
                    VoucherCard(voucher: voucher).frame(width: UIScreen.main.bounds.width - 30, height: (UIScreen.main.bounds.width - 30) * 1)
                }.padding(.top, 15)
           }
    }
}

这是我的详细信息视图,我尝试通过设置purchasedTrue来更新Voucher,然后在List的{​​{1}}中更新

HomeVC

错误:

  

无法分配给属性:函数调用返回不可变的值

代码行:

struct VoucherDetailView: View { @State var voucher: Voucher var didEditVoucher: (Voucher) -> () var body: some View { VStack { Button(action: { self.voucher.purchased = true self.didEditVoucher(self.voucher) }) } } }

照片:

enter image description here

2 个答案:

答案 0 :(得分:1)

这是因为首先仅是吸气剂:

var first: Element? { get }

不是因为VM或observableObject。

您可以尝试这样:

var id = self.VM.vouchers.first(where: { $0.id == "a" })?.id
getVoucher(by id: id).purchased = true

答案 1 :(得分:0)

针对此问题,我在SwiftUI中找到了针对此数据流的最佳解决方案:

https://swiftwithmajid.com/2019/07/03/managing-data-flow-in-swiftui/

要从详细信息视图编辑列表数据,必须使用struct映射列表中的索引,然后在此struct中处理数据

struct IndexedCollection<Base: RandomAccessCollection>: RandomAccessCollection {
    typealias Index = Base.Index
    typealias Element = (index: Index, element: Base.Element)

    let base: Base

    var startIndex: Index { base.startIndex }

    var endIndex: Index { base.endIndex }

    func index(after i: Index) -> Index {
        base.index(after: i)
    }

    func index(before i: Index) -> Index {
        base.index(before: i)
    }

    func index(_ i: Index, offsetBy distance: Int) -> Index {
        base.index(i, offsetBy: distance)
    }

    subscript(position: Index) -> Element {
        (index: position, element: base[position])
    }
}

extension RandomAccessCollection {
    func indexed() -> IndexedCollection<Self> {
        IndexedCollection(base: self)
    }
}

您无需发布通知或观察键值来指示用户界面中的更改,只需使用SwiftUI提供的正确的Property Wrapper。