Просмотр обновления SwiftUI при изменении основного объекта данных - PullRequest
1 голос
/ 09 июля 2020

Проблема, с которой я столкнулся, заключается в том, что когда я обновляю объект основных данных Asset из представления листа, это изменение не отражается в пользовательском интерфейсе AssetListView. (Обратите внимание, что при вставке нового объекта из представления листа выполняется refre sh пользовательский интерфейс AssetListView. Удаление объекта в представлении листа также обновляет пользовательский интерфейс AssetListView) Единственное действие, которое не работает, - это Обновление.

Как я могу изменить AssetListView при изменении основного объекта данных?

У меня есть следующий код SwiftUI, показывающий список ресурсов из CoreData FetchRequest:

struct AssetListView: View {
    @State private var showingSheet = false
    @State private var selectedAssetId: NSManagedObjectID?
    @Environment(\.managedObjectContext) var moc
    @FetchRequest(entity: Asset.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Asset.allocationPercentage, ascending: false)]) var assets: FetchedResults<Asset>
    
    var body: some View {
        VStack {
            Form {
                 ForEach(assets, id: \.self) { asset in
                    Section {
                        AssetRowView(asset: asset)
                            .onTapGesture {
                                self.selectedAssetId = asset.objectID
                                self.showingSheet = true
                        }
                    }
                }
            }
            
        }
        .navigationBarTitle("Assets").sheet(isPresented: $showingSheet ) {
                EditAssetView(assetId: self.selectedAssetId!)
                    .environment(\.managedObjectContext, self.moc)
                }
        }
     }
}

И это экран редактирования, который я представляю как лист SwiftUI:

struct EditAssetView: View {
    var assetId: NSManagedObjectID
    @Environment(\.presentationMode) var presentationMode
    @State private var name = ""
    @State private var description = ""
    @Environment(\.managedObjectContext) var moc
    
    var asset: Asset {
        moc.object(with: assetId) as! Asset
    }
   
    var body: some View {
        NavigationView {
            Form {
                Section {
                    TextField("Name", text: $name)
                    TextField("Description", text: $description)
                }
            }
            .navigationBarTitle(Text("Edit Asset"), displayMode: .inline)
            .navigationBarItems(leading: Button("Cancel") {
                self.presentationMode.wrappedValue.dismiss()
                }, trailing: Button("Done") {
                    self.presentationMode.wrappedValue.dismiss()
                    self.asset.name = self.name
                    self.asset.assetDescription = self.description
                    try? self.moc.save()
                }
            )
        }
        .onAppear {
            self.name = self.asset.name
            self.description = self.asset.assetDescription
        }
    }
}

Вот код для AssetRowView:

struct AssetRowView: View {
    var asset: Asset?
    
    var body: some View {
        HStack {
           Text(asset.name)
           Text(asset.assetDescription)
        }
    }
}

1 Ответ

2 голосов
/ 09 июля 2020

Попробуйте наблюдать Asset (причина NSManagedObject is-a ObservableObject)

struct AssetRowView: View {
    @ObservedObject var asset: Asset        // << here !!
    
    var body: some View {
        HStack {
           Text(asset.name)
           Text(asset.assetDescription)
        }
    }
}

, если этого будет недостаточно, также может потребоваться обновить действие кнопки Done как

}, trailing: Button("Done") {
    self.asset.objectWillChange.send()             // << here !!
    self.asset.name = self.name
    self.asset.assetDescription = self.description
    try? self.moc.save()

    // better do this at the end of activity
    self.presentationMode.wrappedValue.dismiss()
}
...