Posts

Post not yet marked as solved
0 Replies
345 Views
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?
Posted
by tylerlw82.
Last updated
.
Post marked as solved
3 Replies
523 Views
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!
Posted
by tylerlw82.
Last updated
.
Post not yet marked as solved
0 Replies
790 Views
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!
Posted
by tylerlw82.
Last updated
.
Post not yet marked as solved
2 Replies
576 Views
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!
Posted
by tylerlw82.
Last updated
.
Post not yet marked as solved
2 Replies
846 Views
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) } }
Posted
by tylerlw82.
Last updated
.
Post not yet marked as solved
5 Replies
805 Views
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)     } }
Posted
by tylerlw82.
Last updated
.
Post not yet marked as solved
2 Replies
1.4k Views
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&lt;AccountBackEnd&gt;     //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: "")                 }             }                     }
Posted
by tylerlw82.
Last updated
.
Post not yet marked as solved
6 Replies
2.5k Views
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&lt;AccountBackEnd&gt; //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&lt;AccountBackEnd&gt; //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) } }
Posted
by tylerlw82.
Last updated
.