Hi Everyone,
I'm working on a project that requires a core data store, that sends to a ForEach list. I ended up consulting with an online mentor, who was pretty good at helping me make sense of most of my issues. Honestly, he's great. However, after we were done chatting the other night, I hadn't bothered to check that my ForEach list would still work. Sadly it does not, although the rest of the app seems to be ok.
Right now the app builds without issue and runs properly. I can add an attribute, which is part of an entity, and click save. There are no errors present. However, when I go to see my list, there is nothing there.
For more detail, the app works by giving the user several fields to fill out, and that data is then stored in Core Data. I'm pretty confident that the data is stored properly, as it prints out in the log. The log basically presents the several fields, and if there's data, that data is presented there. So for example, the field I'm using to test this is accountCompanyName. If I run the app, and then enter 'Test Account', that 'Test Account' is entered in the log beside accountCompanyName.
I think my problem is some where in my list view, although I'm not 100% sure. I will put code below. I'm also pretty sure that it's the important code, but if something is missing, please let me know.
I'm hoping this is a simple fix, as I'd rather not spend the money on my mentor if I can avoid it! Fingers crossed! I've tried for several hours and haven't had much luck.
Thanks!
This is where I initialize a functoin call that accesses the core data persitent store. It also has several other methods that are part of the build.
import SwiftUI
import CoreData
import Combine
class RefactoringAccount: ObservableObject {
let container: NSPersistentContainer
@Published var savedAccounts: [AccountBackEnd] = []
//Ben Gottlieb Addition
static let refactoringAccountSingleton = RefactoringAccount()
//Ben Gottlieb Addition
func setup() { }
var contextDidSaveCancellable: AnyCancellable?
//Init, creates the NSPersistentContainer
private init(inMemory: Bool = false) {
container = NSPersistentContainer(name: "rangerCoreData")
container.loadPersistentStores{ (description, error) in
if let error = error {
print("Error: \(error)")
} else {
print("All good.")
}
}
fetchAccount()
//Ben Gottlieb addition
let publisher = NotificationCenter.default.publisher(for: NSManagedObjectContext.didSaveObjectsNotification, object: container.viewContext)
contextDidSaveCancellable = publisher
.receive(on: RunLoop.main)
.sink { _ in
self.fetchAccount()
}
}
//Fetch Account Reqeust
func fetchAccount() {
let request = NSFetchRequest<AccountBackEnd>(entityName: "AccountBackEnd")
//I think this is where I put NSPredicate calls for filtering
do {
savedAccounts = try container.viewContext.fetch(request)
} catch let error {
print("Error: \(error)")
}
}
//Add Account
func addAccount(text: String) {
let newAccount = AccountBackEnd(context: container.viewContext)
newAccount.accountCompanyName = text
//++ Rest of accountBackEnd entities go here ++//
saveAccountData()
}
//Delete Accouunt
func deleteAccount(indexSet: IndexSet) {
guard let index = indexSet.first else { return }
let entity = savedAccounts[index]
container.viewContext.delete(entity)
saveAccountData()
}
//Save Account Data
func saveAccountData() {
do {
try container.viewContext.save()
fetchAccount()
} catch let error {
print("Error: \(error)")
}
}
}
This is the view that has my forEach list. This is the par that should be displaying data, but isn't. The first stuct, AddAccountContainer, was something I added from the help of my mentor. I'm still new to it, so I'm still learning what it does.
import SwiftUI
import CoreData
struct AddAccountContainer: View {
@State var account: AccountBackEnd?
func newAccount() -> AccountBackEnd {
let context = RefactoringAccount.refactoringAccountSingleton.container.viewContext
let newAccount = AccountBackEnd(context: context)
return newAccount
}
var body: some View {
VStack() {
if let account = self.account {
AddAccountView(accountBackEnd: account)
}
}
.onAppear {
if account == nil { account = newAccount() }
}
}
}
struct DatabaseViewMain: View {
//var accountBackEnd: FetchedResults<AccountBackEnd>?
@StateObject var refactoringAccount = RefactoringAccount.refactoringAccountSingleton
//From Ben Gottlieb
//@ObservedObject var refactoringAccount = RefactoringAccount.refactoringAccountSingleton
var body: some View {
VStack {
HStack {
Spacer()
NavigationLink {
//Ben Gottlieb Adition
AddAccountContainer()
} label: {
SubHeaderViewIcon(subheaderIcon: "plus.square", subheaderIconColor: Color("EditButtonBlue"))
}
.padding()
}
List {
ForEach(refactoringAccount.savedAccounts) {account in
NavigationLink {
AccountDetailMain(accountBackEnd: account)
} label: {
Text(account.accountCompanyName)
}
.foregroundColor(.red)
}
.onDelete(perform: refactoringAccount.deleteAccount)
}
.listStyle(PlainListStyle())
}
.navigationBarHidden(true)
}
}