@State var documents: [ScanDocument] = []
func loadDocuments() {
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext =
appDelegate.persistentContainer.viewContext
let fetchRequest =
NSFetchRequest<NSManagedObject>(entityName: "ScanDocument")
do {
documents = try managedContext.fetch(fetchRequest) as! [ScanDocument]
print(documents.compactMap({$0.name}))
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
}
}
In the first view:
.onAppear(){
self.loadDocuments()
}
Now I'm pushing to detail view one single object:
NavigationLink(destination: RenameDocumentView(document: documents[selectedDocumentIndex!]), isActive: $pushActive) {
Text("")
}.hidden()
In RenameDocumentView:
var document: ScanDocument
Also, one function to update the document name:
func renameDocument() {
guard !fileName.isEmpty else {return}
document.name = fileName
try? self.moc.save()
print(fileName)
self.presentationMode.wrappedValue.dismiss()
}
All this code works. This print statement always prints updated value:
print(documents.compactMap({$0.name}))
Here's the list code in main View:
List(documents, id: \.id) { item in
ZStack {
DocumentCell(document: item)
}
}
But where user comes back to previous screen. The list shows old data. If I restart the app it shows new data.
Any help of nudge in a new direction would help.
There is a similar question here: SwiftUI List View not updating after Core Data entity updated in another View, but it's without answers.
But make sure to use SwiftUI as the “Interface” mode and SwiftUI App as the “Life Cycle” mode. Also, make sure that you check the “Use Core Data” box. This will automatically set up the initial Core Data implementation for our app! Make sure you “reset” the ContentView by removing the generated code from it since we won’t need it for our app.
You can name your project however you want, for instance, “PizzaRestaurant”. But make sure to use SwiftUI as the “Interface” mode and SwiftUI App as the “Life Cycle” mode. Also, make sure that you check the “Use Core Data” box.
To get started, open Xcode 12 and create a new “App” under “Multiplatform” or “iOS”. You can name your project however you want, for instance, “PizzaRestaurant”. But make sure to use SwiftUI as the “Interface” mode and SwiftUI App as the “Life Cycle” mode. Also, make sure that you check the “Use Core Data” box.
The simplest way to fetch data using a fetch request while responding to any changes that impact your fetch request's results is to use an NSFetchResultsController. While this object is commonly used in conjunction with table views and collection views, we can also use it to drive a SwiftUI view. Let's look at some code:
NSManagedObject
is a reference type so when you change its properties your documents
is not changed, so state does not refresh view.
Here is a possible approach to force-refresh List when you comes back
@State var documents: [ScanDocument] = []
@State private var refreshID = UUID() // can be actually anything, but unique
List(documents, id: \.id) { item in
ZStack {
DocumentCell(document: item)
}
}.id(refreshID) // << here
NavigationLink(destination: RenameDocumentView(document: documents[selectedDocumentIndex!])
.onDisappear(perform: {self.refreshID = UUID()}),
isActive: $pushActive) {
Text("")
}.hidden()
Alternate: Possible alternate is to make DocumentCell
observe document, but code is not provided so it is not clear what's inside. Anyway you can try
struct DocumentCell: View {
@ObservedObject document: ScanDocument
...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With