Hi Everyone,
I'm coming to you hat-in-hand again, as I'm really struggling with a point of my app that keeps crashing when I go to click on a cell in my list. Namely I get this error: Thread 1: "-[AccountBackEnd accountCompanyName]: unrecognized selector sent to instance 0x6000025aac40.". This appears right on the line of @main in the file that renders the app's output. To make matters worse, this is in SwiftUI and there doesn't seem to be a lot of documentation on this error online.
I'm not 100% sure, but I think it's got something to do with a syste for navigation that I downloaded, I was using which was meant to make navigation simpler. I don't think that's the case here. I've begun the process of going away from that system of buttons to use the more conventional NavigationView and NavigationLink.
I've managed to deal with a few errors already here, but this one seems to be kicking my **** pretty badly. I'm at a loss. I'll put my code below for your review.
As always, any help here is greatly, greatly appreciated.
Database view, this contains the app's list
struct DatabaseViewMain: View {
//Fetch request for pulling from persistent store.
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \AccountBackEnd.accountCompanyName, ascending: true)],
animation: .default)
private var accounts: FetchedResults<AccountBackEnd>
//Calls to Class for published objects
@EnvironmentObject var publishedClasses: PublishedClasses
//Takes object from @StateObject, presents as var
@ObservedObject var accountBackEnd: AccountBackEnd = AccountBackEnd()
var body: some View {
VStack {
HStack {
Spacer()
NavigationLink {
AddAccountView()
} label: {
SubHeaderViewIcon(subheaderIcon: "plus.square", subheaderIconColor: Color("EditButtonBlue"))
}
.padding()
}
List {
ForEach(accounts, id: \.self) {account in
NavigationLink {
AccountDetailMain(accountBackEnd: accountBackEnd)
} label: {
Text(account.accountCompanyName ?? "")
}
}
.onDelete(perform: deleteAccounts)
.environmentObject(publishedClasses)
}
.listStyle(PlainListStyle())
}
.navigationBarHidden(true)
.environmentObject(publishedClasses)
}
//Deleting Account
private func deleteAccounts(offsets: IndexSet) {
withAnimation {
offsets.map { accounts[$0] }.forEach(viewContext.delete)
do {
try viewContext.save()
} catch {
print("Shit. Something happened. Error \(error.localizedDescription)")
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}
}
AccountDetailMain, this presents the user with their Account's info.
I believe this is the part that is actually crashing the app?
struct AccountDetailMain: View {
//Managed Object Context Call
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \AccountBackEnd.accountID, ascending: true)],
animation: .default)
private var accounts: FetchedResults<AccountBackEnd>
//Calls from @Published
@EnvironmentObject var publishedClasses: PublishedClasses
//Takes object from @StateObject, presents as var
@ObservedObject var accountBackEnd: AccountBackEnd
var body: some View {
ScrollView {
VStack {
MainHeaderViewTop(mainTextField: accountBackEnd.accountCompanyName ?? "", iconField: "building")
}
.environmentObject(publishedClasses)
Spacer()
.frame(height: 5)
HStack {
NavigationLink {
EditAccountView()
} label: {
MainHeaderViewBottomLeft()
}
Spacer()
NavigationLink {
AddAccountView()
} label: {
SubHeaderViewIcon(subheaderIcon: "plus.square", subheaderIconColor: Color("EditButtonBlue"))
}
}
ViewSpacer()
Group {
SalesRecords()
ViewSpacer()
LatestThreeQuotes()
ViewSpacer()
LatestNote()
ViewSpacer()
}
Group {
AccountsContactsView()
ViewSpacer()
BranchContactInfoView()
ViewSpacer()
AccountAddressView()
ViewSpacer()
RepDetailsView()
ViewSpacer()
}
Group {
NavigationLink {
EditAccountView()
} label: {
LargeEditButtonGreen(editButtonLabel: "Edit Account")
}
ViewSpacer()
}
.environmentObject(publishedClasses)
}
.navigationBarHidden(true)
.environmentObject(publishedClasses)
}
}
Post
Replies
Boosts
Views
Activity
Hi Everyone,
I'm trying to get my SwiftUI project to work with Core Data, and to be refactored. I'm using property wrappers for its fetch request.
I keep getting this error in the log: "Accessing StateObject's object without being installed on a View. This will create a new instance each time."
As far as I know, it's something to do with having multiple @StateObject requests. Is this correct?
What am I doing wrong here?
I'll try and add my relevant code below. Any help here is greatly appreciated. Alternatively I can send you a link to my GH .
my refactoring\modelview file
import SwiftUI
class RefactorAccounts: ObservableObject {
//Fetch request for pulling from persistent store.
@Environment(\.managedObjectContext) var viewContext
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \AccountBackEnd.accountCompanyName, ascending: true)],
animation: .default)
var accounts: FetchedResults<AccountBackEnd>
//Takes object from @StateObject, presents as var
@StateObject var accountBackEnd = AccountBackEnd()
//Calls to Class for published objects
@StateObject var publishedClasses =
PublishedClassAccount()
//Used for button/nav calls out
@Environment(\.presentationMode) var presentationMode
//Add account Function
func addAccount() {
withAnimation {
//Adds to persistence store
let newAccount = AccountBackEnd(context: viewContext)
newAccount.accountCompanyName = publishedClasses.accountNameForCoreData
PersistenceController.shared.save
{
error in
if let error = error {
print(error.localizedDescription)
return
}
print("Successfully saved account.")
}
self.presentationMode.wrappedValue.dismiss()
publishedClasses.accountNameForCoreData = ""
}
}
}
The file that displays clickable data
//Refactoring
@StateObject var refAccouunts = RefactorAccounts()
//Used for button/nav calls out
@Environment(\.presentationMode) var presentationMode
var body: some View {
VStack {
HStack {
Spacer()
NavigationLink {
AddAccountView()
} label: {
SubHeaderViewIcon(subheaderIcon: "plus.square", subheaderIconColor: Color("EditButtonBlue"))
}
.padding()
}
List {
ForEach(refAccouunts.accounts, id: \.id) {account in
NavigationLink {
AccountDetailMain()
} label: {
Text(account.accountCompanyName ?? "")
}
.foregroundColor(.red)
}
.onDelete(perform: deleteAccounts)
}
.listStyle(PlainListStyle())
}
.navigationBarHidden(true)
}
View that is used to add data, from sub views.
@ObservedObject var refAccouunts = RefactorAccounts()
//Used for button/nav call out
@Environment(\.presentationMode) var presentationMode
var body: some View {
ScrollView {
VStack {
Group {
MainAddHeaderView(mainTextField: "Account", iconField: "building")
}
Group{
AddAccountCompanyName()
ViewSpacer()
AddAccountAddress()
ViewSpacer()
AddAccountDetails()
ViewSpacer()
Button(action: refAccouunts.addAccount) {
LargeSaveButtonBlue(saveButtonLabel: "Save Changes")
}
}
ViewSpacer()
LargeDeleteButton(deleteButtonLabel: "Cancel Changes")
ViewSpacer()
}
}
.environmentObject(refAccouunts.publishedClasses)
.navigationBarHidden(true)
}
Specific sub-view
//Refactoring
@ObservedObject var refAccouunts = RefactorAccounts()
//Used for button/nav call out
@Environment(\.presentationMode) var presentationMode
var body: some View {
VStack {
HStack {
SubHeaderViewText(subheaderTitle: "Account")
NavigationLink {
AddContactView()
} label: {
SubHeaderViewIcon(subheaderIcon: "plus.square", subheaderIconColor: Color("EditButtonBlue"))
}
}
Spacer()
.frame(height: 20)
Group {
VStack (alignment: .leading) {
Text("Account Name")
.frame(alignment: .leading)
.modifier(AddRangerHeaderStyle())
.font(.custom("SF Pro Display Light", fixedSize: 20))
.foregroundColor(Color("DarkerGrey"))
TextField("Account Name", text: refAccouunts.$publishedClasses.accountNameForCoreData)
.textFieldStyle(AddRangerTextFieldStyle())
HStack {
RangerTextField(labelText: "First Name", placeHolder: "")
RangerTextField(labelText: "Last Name", placeHolder: "")
}
RangerTextField(labelText: "Position", placeHolder: "")
}
}
}
Hi Everyone,
I'm trying to refactor a function to make less future errors in my code. I think I'm doing it the right way, but I keep coming across this error, "No ObservableObject of type PublishedClassAccount found. A View.environmentObject(_:) for PublishedClassAccount may be missing as an ancestor of this view."
I will put my code below, but please let me know if I've missed anything. I keep reading online that it has something to do with needing to add an EnvironmentObject, but I can't make sense of it past that. I've been trying to refactor this for weeks and still not getting anywhere. Once I've learned this I'll apply this refactor to other views that will need it.
Any help here is greatly appreciated!
Thank you!
This is the class that I'm trying to refactor to. I've added all of the objects to it that needed to be. Error happens on the line that reads, "newAccount.accountCompanyName = publishedClassAccount.accountCompanyNamePublished":
import SwiftUI
class funcTest: ObservableObject {
//Handles the in-out with the CoreData persistence store
@Environment(\.managedObjectContext) var viewContext
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \AccountBackEnd.accountID, ascending: true)],
animation: .default)
var accounts: FetchedResults<AccountBackEnd>
//Access Published Objects
@EnvironmentObject var publishedClassAccount: PublishedClassAccount
//Used for button/nav call out
@Environment(\.presentationMode) var presentationMode
func addAccount() {
withAnimation {
//Adds to persistence store
let newAccount = AccountBackEnd(context: viewContext)
newAccount.accountCompanyName = publishedClassAccount.accountCompanyNamePublished
newAccount.accountAddress = publishedClassAccount.accountAddressPublished
PersistenceController.shared.save
{
error in
if let error = error {
print(error.localizedDescription)
return
}
print("Successfully saved account.")
}
//Exits view
self.presentationMode.wrappedValue.dismiss()
publishedClassAccount.accountCompanyNamePublished = ""
}
}
}
This is the view that first allows the user to add an account:
import SwiftUI
import CoreData
//View for user to add a new account with
struct AddAccountView: View {
//Handles the in-out with the CoreData persistence store
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \AccountBackEnd.accountID, ascending: true)],
animation: .default)
private var accounts: FetchedResults<AccountBackEnd>
//Access Published Objects
@EnvironmentObject var publishedClasses: PublishedClassAccount
//Used for button/nav call out
@Environment(\.presentationMode) var presentationMode
//Calls func for refactoring
@StateObject var vm = funcTest()
var body: some View {
ScrollView {
VStack {
Group {
MainAddHeaderView(mainTextField: "Account", iconField: "building")
}
Group{
AddAccountCompanyName()
ViewSpacer()
AddAccountAddress()
ViewSpacer()
AddAccountDetails()
ViewSpacer()
Button(action: vm.addAccount) {
LargeSaveButtonBlue(saveButtonLabel: "Save Changes")
}
.environmentObject(publishedClasses)
}
ViewSpacer()
LargeDeleteButton(deleteButtonLabel: "Cancel Changes")
ViewSpacer()
}
}
.navigationBarHidden(true)
}
}
And this is the view that is meant to display the Account after it's been entered:
import SwiftUI
import CoreData
struct AccountDetailMain: View {
//Takes object from @StateObject, presents as var
@ObservedObject var accountBackEnd: AccountBackEnd
var body: some View {
ScrollView {
VStack {
MainHeaderViewTop(mainTextField: accountBackEnd.accountCompanyName ?? "", iconField: "building")
}
Spacer()
.frame(height: 5)
HStack {
NavigationLink {
EditAccountView()
} label: {
MainHeaderViewBottomLeft()
}
Spacer()
NavigationLink {
AddAccountView()
} label: {
SubHeaderViewIcon(subheaderIcon: "plus.square", subheaderIconColor: Color("EditButtonBlue"))
}
}
ViewSpacer()
Group {
SalesRecords()
ViewSpacer()
LatestThreeQuotes()
ViewSpacer()
LatestNote()
ViewSpacer()
}
Group {
AccountsContactsView()
ViewSpacer()
BranchContactInfoView()
ViewSpacer()
AccountAddressView()
ViewSpacer()
RepDetailsView()
ViewSpacer()
}
Group {
NavigationLink {
EditAccountView()
} label: {
LargeEditButtonGreen(editButtonLabel: "Edit Account")
}
ViewSpacer()
}
}
.navigationBarHidden(true)
//.environmentObject(publishedClasses)
}
}
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)
}
}
Hi Everyone,
This is a long read, but it comes from my biggest frustration and lack of knowledge in SwiftUI, and how it relates to my own project. It’s the thing about injecting un-initialized objects into views. So something like, “AccountViewMain()”, will need to have a value if there’s a variable in AccountViewMain, that’s not initialized. From what I know, every object needs to be initialized. I think I’m right about that. I’ll add my code below.
For the most part, I can make sense of this. Where I KEEP running into trouble is how this relates to core data, and more specifically some help I received from a code mentor I connected with. The mentor was great, but expensive. Christmas is coming up so I’ve got to be careful with how much I spend.
My project has several views that reference my core data persistent store. My mentor used Combine to make it so whenever a user clicks the add button, a new object is already stored in the persistent store. So that when you go back to the list that presents those different objects (in my case accounts), they all show up, even with nothing in them. If I add text to that object, it shows up. But the problem is that whenever a user just clicks to a new object(account), the app automatically creates it. Not a desired effect.
And I know why this happens. It’s because the button I click on runs this code he made. It’s a view that does not ask for injection, and I think that’s because the view my mentor created runs an initializer. This is all cool, but not entirely helpful.
I have another view that looks just like the one my mentor made, but it doesn’t do any of the adding. So I want mine to appear when the user clicks to add a new object, and then use some of the code my mentor wrote to save the new entry whenever a user clicks the save button. This is the desired effect.
Here’s where I run into issues, even though my core data persistent store gets initialized, when I try to add my own view, it keeps saying, “Missing Parameter for accountBackEnd…” So this is assuming that the view called AccountViewMain, has a line like “@ObservedObject var accountBackEnd: AccountBackEnd. For reference, AccountBackEnd is the name of my core data entity. I’ve set everything else up, so it’s all good, but like I said, I run into issues here.
When I add the appropriate objects between the braces, it seems like it just keeps asking me for more and more. Like I'll fix one, and then the next one down the line asks, until I'm at my @main view. When I add it here, it says something about needing to be initialized. I'm pretty sure there's not supposed to be one there. Right?
I’ve tried adding “*** = AccountBackEnd()” to the end of that line, but naturally that doesn’t work. I think it’s something to do with the “= ***()” meaning that it’s recreating that view. Not referencing it. To add to this, whenever I try to look up how to initialize online, I really don’t get anywhere.
Is there someone who could please help me understand what it is that I should be doing here?
I’ll add what I think is pertinent code below. Please let me know if there is anything I’m missing here as far as code goes.
Thank you all kindly!
Hi Folks,
I’m noticing that the charts system I have presents the time of day that something was entered, if it’s a single value. Not the date.
So for reference, my chart displays dollar value on the Y axis, and day that value was entered, on the X axis.
if I have multiple values entered, it will display the dates. Cool. Although if it’s just one value, it displays the time it was entered, not the date. Which is not great.
is there any way to adjust this so it displays the date, regardless of how many values are entered?
Thsnks!
Hi everyone,
If I’m using SF Symbols in my app, am I allowed to use those same symbols on my app’s website? So in other words, I've used SF Symbols in my app to indicate what certain things are. For example "person.fill" to indicate a contact of a person.
So now that I'm at a point where I'm developing a site for my app, I'm hoping to use those same symbols to indicate what they are for when the user uses the app.
Seems a little silly that I might not be able to use them on my app, but I can’t use them to indicate what they’re for on my site?
Thanks!
In other words, I’m trying to setup sharing in my app using Core Data with CloudKit. Basically the user can share their list of CloudKit records with other users of the app. Should that other user accept that share from that share-sender, the share-receiver can then sees the sender’s list of records. This part works as I need it to. This is fine. As well, the app is largely being written in SwiftUI.
However, what I also need is to give the user the ability to see only their own records, or to set one of their records to private. I think I can figure this logic out, but I’m still not sure of how to filter the sender versus receiver of that share, AKA owner vs participant.
I’ve tried several things to figure this out, and I keep coming up empty. I feel like there’s a good way to do this, however what I’ve done always has issues.
Can someone please describe the best way to do this?
I’m using ‘Offer Codes’ in App Store Connect for subscriptions. I’m also using a StoreKit implementation that uses the subscriptionStatusTask modifier to assess if the user is subscribed or not.
The part I’m not sure of is whether or not the subscriptionStatusTask modifier will recognize the status if the user has used an offer code. I think it should, as that modifier checks for currentEntitlements, and returns appropriately.
I’ve been trying to test this out with the StoreKitTransactions system in Xcode, as SandBox does not currently support this. From what I can tell, this way does in fact seem to allow the user to access the app with an offer code. The app does not present the StoreKit view.
However, when I’ve tried this with an actual user on the app store (aren’t mom’s great?), the offer code does not take, and they are presented with that StoreKit view. Not great.
So can someone please shed some light on this? Is my understanding correct here? What else do I need to do?