Post

Replies

Boosts

Views

Activity

Reply to CoreData not updating Property
hi, we do not see the definition of category in this view, but i am hoping that it would ideally be @ObservedObject var category: Category // not an optional, so reference category.CitemsArray in the ForEach you should know that changing a property of one of the category's associated items is not seen as a change to the category object itself, and it will not trigger a visual update of the view. when you do item.done.toggle() in the .onTapGesture, consider registering an explicit change on the category object with category.objectWillChange.send() hope that helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
May ’21
Reply to CloudKit and CoreData synchronization
hi, it may be as simple as not turning on history tracking. in my code, i usually have these lines right after creating the NSPersistentCloudKitContainer: // (1) Enable history tracking. this seems to be important when you have more than one persistent // store in your app (e.g., when using the cloud) and you want to do any sort of cross-store // syncing. See WWDC 2019 Session 209, "Making Apps with Core Data." guard let persistentStoreDescription = container.persistentStoreDescriptions.first else { fatalError("\(#function): Failed to retrieve a persistent store description.") } persistentStoreDescription .setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey) persistentStoreDescription .setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey) hope that helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Jun ’21
Reply to How to manage manual ordering of entities in Core Data?
Yup, it's one year later, and things have changed. i did indeed find out that iCloud does not work with an Ordered relationship. in the end, there were only two, fixed image data objects i needed: one for a 48 by 48 image, and one for a 144 by 144 image. i just made them attributes of an Entity, rather than separate Entities via a relationship that are indexed 0 ... 1, with a reasonable compression value. i marked the attributes in Core Data as "Allows External Storage." if i run into problems in the future, i will come back to it (!) DMG
Jun ’21
Reply to Manually define a CKRecord ID for a given NSManagedObject instance
hi, since you are using NSPersistentCloudKitContainer, you might want to take a look at Apple's page on Linking Data Between Two Core Data Stores. this provides a mechanism so that you can load up what i think you are calling "base values" in a local store, separate from the store that is mirrored to iCloud. this would solve the problem of loading base values on one machine, moving them into the cloud, and then trying to figure out on a second device how to prevent them from being reloaded from iCloud. hope that helps, DMG
Jul ’21
Reply to What are Apple's plan for Transformable Custom class [Double]
hi, i think you should take the error message as is and paste the string NSSecureUnarchiveFromDataTransformerName directly into the Transformer entry where it indicates "Value Transformer name". that will do it. as to what this means in the future: who knows? i doubt that it will go away. this has more to do with security rather than any feature that will be changing. as for best practices: transformable data is not directly searchable in Core Data. that doesn't mean that you cannot search by dates, pulling all records and then, one-by-one, examining its array of dates. it's just that Core Data cannot do it with a simple fetch. hope that helps, DMG
Jul ’21
Reply to @FetchRequest in a class, SwiftUI
hi, you can certainly do a fetch directly with core data; but if you expect your class object to find out about changes in Core Data and act like you had a @FetchRequest, you would want to use an NSFetchedResultsController in your object to see changes over time. hope that helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Sep ’21
Reply to Separating CoreData functionality from the View (SwiftUI) but Still with observability
hi, your ViewModel simply needs to use an NSFetchedResultsController to hook into Core Data, and keep the array of Core Data objects that you would ordinarily define in the View (using @FetchRequest) as a @Published property. whenever the resultsController fires, update the array property. be sure your View keeps a reference to the ViewModel as an @ObservedObject. hope that helps, DMG
Jan ’22
Reply to How to increase or decrease the probability of an item being picked from an array?
hi, the easiest, fastest way might just be to change the definition of numbers, so that the elements appears with the frequencies you like. since we're talking 1/20-ths here (multiples of 5%), give the array 20 elements: let numbers = ["1", "1", "2", "2", "2", "2", "3", "3", "3", "3", "3", "3", "4", "4", "4", "4", "4", "4", "4", "5"] if let pickedNumber = numbers.randomElement() { print(pickedNumber) } there are more general ways to do this, but keep it simple for now .. hope that helps, DMG
Feb ’22
Reply to NSPersistentCloudKitContainer exclude relationship from share
hi, ... this may not directly answer your CloudKit sharing, but what you may be asking is how to place all Core Data Folder and Comment objects into a local persistent store configuration, and allItem objects into a cloud configuration that is shared with iCloud. if that's the case, you cannot implement direct relationships between configurations, so then you might: in every Item, store the id: UUID of the Folder it belongs to (you do put UUIDs into your Core Data entities, yes?) ... sort of a parentID, and in every Comment, store the id: UUID of the Item it belongs to, again, essentially a parentID. you can then finesse the relationships, say for an Item, finding its parent Folder by doing a Core Data fetch for Folder objects whose id matches the Item's parentID; and similarly, you can locate the Comments associated with an Item by doing a Core Data fetch for Comment objects whose parentID matches the Item's id. Also take a look at this Apple Sample project on how to handle separate stores in Core Data. hope that helps, DMG
Feb ’22
Reply to Using NSSortDescriptor(key: "date", ascending: true
hi, you do not show the definition of your Core Data entity, nor the type of its attribute "date." since the list of dates appears to be sorted alphabetically, i am guessing that you defined the date attribute in Core Data as a String (not as a Date) and that you are storing strings in what you call "date." that would explain the result above. (BTW: to have Core Data sort by the Date type, you would want "ascending: false" for the NSSortDescriptor so that the most recent date comes out first.) hope that helps, DMG
Feb ’22
Reply to Using NSSortDescriptor(key: "date", ascending: true
Drew, some quick comments, since i cannot see your code (if it were available on GitHub, that might be of interest). in the Core Data model editor, find the attribute date in whatever entity you are working with and check that its Type shows as Date. if it shows as String there, just click on the String value and choose Date as the Type from the pull-down menu. (you may already have done this, but i cannot tell from your question.) so Core Data knows the values are dates, and sorting with ascending: false will give most recent dates first, oldest dates last. Xcode will give your app/program access to the date attribute as a Swift variable var date: Date? defined on the class object for your entity. notice that this is an optional Date in Swift, so treat it accordingly when reading it. all your existing code that reads from the date attribute or assigns to the date attribute should be working with real Date objects in Swift. you cannot assign a String to a Date? object; but really, other than for display purposes, you should not be working with string values of dates in your code anyway, since constantly translating back and forth between Strings and Dates is hard. hope that helps, DMG
Mar ’22
Reply to Different Scenarios with Core Data and CloudKit
hi, i would think your easiest solution is to use the built-in linkage between Core Data and CloudKit using NSPersistentCloudKitContainer. this takes care of all of your concerns: your data is stored locally in Core Data and mirrored to/from the cloud for you. everything works fine when offline or not signed in to iCloud. just remember that in this design, the Cloud becomes the "source of truth" for your data. modify data on one device; it is synced with iCloud; and then the data is synced with your other devices, where their local Code Data store is synced to match what's in the cloud. there would be no option for the user here to "choose" which data they want to use, as you say, "the backed-up data or the new data." once your device is online and signed into iCloud, your on-device data will be synced to be a mirror of what's in the cloud. hope that helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Apr ’22
Reply to What's the recommended code structure to manage apps with MVVM+SwiftUI+CoreData
hi, i like your question: Which of the two options above makes more sense for an MVVM app? i have used one, both, sometimes neither, and sometimes variations, and i have not really liked any enough to say that "that's what i'd do" the next time i work on an App. some thoughts: (1) my bottom-line goal is to be sure that no ShiftUI View should be in the business of really knowing that the (class) objects it works with are Core Data objects. for example: i don't ever want a View executing code that uses the managed object context to create a new object or delete an existing object. so some form of VM is needed, whether it be a global singleton or a locally-created @StateObject on a per-view basis. (2) yet a second goal is to avoid building a MVM = "Massive View Model." because you are using Core Data objects, i think your first option might be better, because you have relationships and fetch requests to manage. i think those are better done and centralized by some object that has a global view of the database. (3) remember that with Core Data relationships in play, there are some subtleties that should be handled in a VM. for example: when updating an existing CarService, perhaps in a detail view, the VM will know that it must manually execute carService.car?.objectWillChange.send() so that the associate Car record should be treated as having changed (changing a field in CarService does not do this for you), because you probably have some Views in your app that hold an @ObservedObject Car object reference. (4) you have the decision as to whether you want to use @FetchRequests directly to deliver an array of objects to a view, or have a VM use its own NSFetchedResultsController objects to deliver that array. other than for simple views, such as a List, i have usually chosen the latter. however, even then, i've started to dislike having to begin every SwiftUI view file with the usual litany of property wrappers, one of which is a @FetchRequest that's repeated verbatim in multiple views throughout the app. (5) i usually add a few convenience extensions to the Core Data classes to do simple things, such as nil-coalesce optional fields of the Core Data record, convert between Int and Int32/Int16, or provide a computed variable (one that's especially useful is to return a properly typed Set or Array of CarService objects for a given Car). but i have found it useful to also include creation and deletion functions in that extension as class functions on the Core Data class itself. so instead of writing a "let newService = CarService(context: contact) ..." sequence that defaults and hooks up the new service with an existing Car, i will write a single statement "let newService = CarService.add(to: car, ...)" and leave the details to the CarService class to do the creation, default all the fields, and hook the service to the Car. this simplifies the call site, and is especially useful if there are several points in your app where you add services to a car. hope some of this helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
May ’22
Reply to CoreData not updating Property
hi, we do not see the definition of category in this view, but i am hoping that it would ideally be @ObservedObject var category: Category // not an optional, so reference category.CitemsArray in the ForEach you should know that changing a property of one of the category's associated items is not seen as a change to the category object itself, and it will not trigger a visual update of the view. when you do item.done.toggle() in the .onTapGesture, consider registering an explicit change on the category object with category.objectWillChange.send() hope that helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
May ’21
Reply to CloudKit and CoreData synchronization
hi, it may be as simple as not turning on history tracking. in my code, i usually have these lines right after creating the NSPersistentCloudKitContainer: // (1) Enable history tracking. this seems to be important when you have more than one persistent // store in your app (e.g., when using the cloud) and you want to do any sort of cross-store // syncing. See WWDC 2019 Session 209, "Making Apps with Core Data." guard let persistentStoreDescription = container.persistentStoreDescriptions.first else { fatalError("\(#function): Failed to retrieve a persistent store description.") } persistentStoreDescription .setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey) persistentStoreDescription .setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey) hope that helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Jun ’21
Reply to Refresh value in view SwiftUI
hi, change the declaration var item: Item in DetailView to @ObservedObject var item: Item changes to the item will then trigger a view update for the DetailView. that should do it, i think. hope that helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Jun ’21
Reply to How to manage manual ordering of entities in Core Data?
Yup, it's one year later, and things have changed. i did indeed find out that iCloud does not work with an Ordered relationship. in the end, there were only two, fixed image data objects i needed: one for a 48 by 48 image, and one for a 144 by 144 image. i just made them attributes of an Entity, rather than separate Entities via a relationship that are indexed 0 ... 1, with a reasonable compression value. i marked the attributes in Core Data as "Allows External Storage." if i run into problems in the future, i will come back to it (!) DMG
Replies
Boosts
Views
Activity
Jun ’21
Reply to Manually define a CKRecord ID for a given NSManagedObject instance
hi, since you are using NSPersistentCloudKitContainer, you might want to take a look at Apple's page on Linking Data Between Two Core Data Stores. this provides a mechanism so that you can load up what i think you are calling "base values" in a local store, separate from the store that is mirrored to iCloud. this would solve the problem of loading base values on one machine, moving them into the cloud, and then trying to figure out on a second device how to prevent them from being reloaded from iCloud. hope that helps, DMG
Replies
Boosts
Views
Activity
Jul ’21
Reply to What are Apple's plan for Transformable Custom class [Double]
hi, i think you should take the error message as is and paste the string NSSecureUnarchiveFromDataTransformerName directly into the Transformer entry where it indicates "Value Transformer name". that will do it. as to what this means in the future: who knows? i doubt that it will go away. this has more to do with security rather than any feature that will be changing. as for best practices: transformable data is not directly searchable in Core Data. that doesn't mean that you cannot search by dates, pulling all records and then, one-by-one, examining its array of dates. it's just that Core Data cannot do it with a simple fetch. hope that helps, DMG
Replies
Boosts
Views
Activity
Jul ’21
Reply to @FetchRequest in a class, SwiftUI
hi, you can certainly do a fetch directly with core data; but if you expect your class object to find out about changes in Core Data and act like you had a @FetchRequest, you would want to use an NSFetchedResultsController in your object to see changes over time. hope that helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Sep ’21
Reply to Core Data Predicate with UUID attribute
hi, why not simply write the predicate as NSPredicate(format: "clientId == %@", clientId! as CVarArg) // i would think the force unwrap would help here ? i have used this; it works. hope that helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Sep ’21
Reply to Separating CoreData functionality from the View (SwiftUI) but Still with observability
hi, your ViewModel simply needs to use an NSFetchedResultsController to hook into Core Data, and keep the array of Core Data objects that you would ordinarily define in the View (using @FetchRequest) as a @Published property. whenever the resultsController fires, update the array property. be sure your View keeps a reference to the ViewModel as an @ObservedObject. hope that helps, DMG
Replies
Boosts
Views
Activity
Jan ’22
Reply to How to increase or decrease the probability of an item being picked from an array?
hi, the easiest, fastest way might just be to change the definition of numbers, so that the elements appears with the frequencies you like. since we're talking 1/20-ths here (multiples of 5%), give the array 20 elements: let numbers = ["1", "1", "2", "2", "2", "2", "3", "3", "3", "3", "3", "3", "4", "4", "4", "4", "4", "4", "4", "5"] if let pickedNumber = numbers.randomElement() { print(pickedNumber) } there are more general ways to do this, but keep it simple for now .. hope that helps, DMG
Replies
Boosts
Views
Activity
Feb ’22
Reply to NSPersistentCloudKitContainer exclude relationship from share
hi, ... this may not directly answer your CloudKit sharing, but what you may be asking is how to place all Core Data Folder and Comment objects into a local persistent store configuration, and allItem objects into a cloud configuration that is shared with iCloud. if that's the case, you cannot implement direct relationships between configurations, so then you might: in every Item, store the id: UUID of the Folder it belongs to (you do put UUIDs into your Core Data entities, yes?) ... sort of a parentID, and in every Comment, store the id: UUID of the Item it belongs to, again, essentially a parentID. you can then finesse the relationships, say for an Item, finding its parent Folder by doing a Core Data fetch for Folder objects whose id matches the Item's parentID; and similarly, you can locate the Comments associated with an Item by doing a Core Data fetch for Comment objects whose parentID matches the Item's id. Also take a look at this Apple Sample project on how to handle separate stores in Core Data. hope that helps, DMG
Replies
Boosts
Views
Activity
Feb ’22
Reply to Using NSSortDescriptor(key: "date", ascending: true
hi, you do not show the definition of your Core Data entity, nor the type of its attribute "date." since the list of dates appears to be sorted alphabetically, i am guessing that you defined the date attribute in Core Data as a String (not as a Date) and that you are storing strings in what you call "date." that would explain the result above. (BTW: to have Core Data sort by the Date type, you would want "ascending: false" for the NSSortDescriptor so that the most recent date comes out first.) hope that helps, DMG
Replies
Boosts
Views
Activity
Feb ’22
Reply to Using NSSortDescriptor(key: "date", ascending: true
Drew, some quick comments, since i cannot see your code (if it were available on GitHub, that might be of interest). in the Core Data model editor, find the attribute date in whatever entity you are working with and check that its Type shows as Date. if it shows as String there, just click on the String value and choose Date as the Type from the pull-down menu. (you may already have done this, but i cannot tell from your question.) so Core Data knows the values are dates, and sorting with ascending: false will give most recent dates first, oldest dates last. Xcode will give your app/program access to the date attribute as a Swift variable var date: Date? defined on the class object for your entity. notice that this is an optional Date in Swift, so treat it accordingly when reading it. all your existing code that reads from the date attribute or assigns to the date attribute should be working with real Date objects in Swift. you cannot assign a String to a Date? object; but really, other than for display purposes, you should not be working with string values of dates in your code anyway, since constantly translating back and forth between Strings and Dates is hard. hope that helps, DMG
Replies
Boosts
Views
Activity
Mar ’22
Reply to Different Scenarios with Core Data and CloudKit
hi, i would think your easiest solution is to use the built-in linkage between Core Data and CloudKit using NSPersistentCloudKitContainer. this takes care of all of your concerns: your data is stored locally in Core Data and mirrored to/from the cloud for you. everything works fine when offline or not signed in to iCloud. just remember that in this design, the Cloud becomes the "source of truth" for your data. modify data on one device; it is synced with iCloud; and then the data is synced with your other devices, where their local Code Data store is synced to match what's in the cloud. there would be no option for the user here to "choose" which data they want to use, as you say, "the backed-up data or the new data." once your device is online and signed into iCloud, your on-device data will be synced to be a mirror of what's in the cloud. hope that helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Apr ’22
Reply to What's the recommended code structure to manage apps with MVVM+SwiftUI+CoreData
hi, i like your question: Which of the two options above makes more sense for an MVVM app? i have used one, both, sometimes neither, and sometimes variations, and i have not really liked any enough to say that "that's what i'd do" the next time i work on an App. some thoughts: (1) my bottom-line goal is to be sure that no ShiftUI View should be in the business of really knowing that the (class) objects it works with are Core Data objects. for example: i don't ever want a View executing code that uses the managed object context to create a new object or delete an existing object. so some form of VM is needed, whether it be a global singleton or a locally-created @StateObject on a per-view basis. (2) yet a second goal is to avoid building a MVM = "Massive View Model." because you are using Core Data objects, i think your first option might be better, because you have relationships and fetch requests to manage. i think those are better done and centralized by some object that has a global view of the database. (3) remember that with Core Data relationships in play, there are some subtleties that should be handled in a VM. for example: when updating an existing CarService, perhaps in a detail view, the VM will know that it must manually execute carService.car?.objectWillChange.send() so that the associate Car record should be treated as having changed (changing a field in CarService does not do this for you), because you probably have some Views in your app that hold an @ObservedObject Car object reference. (4) you have the decision as to whether you want to use @FetchRequests directly to deliver an array of objects to a view, or have a VM use its own NSFetchedResultsController objects to deliver that array. other than for simple views, such as a List, i have usually chosen the latter. however, even then, i've started to dislike having to begin every SwiftUI view file with the usual litany of property wrappers, one of which is a @FetchRequest that's repeated verbatim in multiple views throughout the app. (5) i usually add a few convenience extensions to the Core Data classes to do simple things, such as nil-coalesce optional fields of the Core Data record, convert between Int and Int32/Int16, or provide a computed variable (one that's especially useful is to return a properly typed Set or Array of CarService objects for a given Car). but i have found it useful to also include creation and deletion functions in that extension as class functions on the Core Data class itself. so instead of writing a "let newService = CarService(context: contact) ..." sequence that defaults and hooks up the new service with an existing Car, i will write a single statement "let newService = CarService.add(to: car, ...)" and leave the details to the CarService class to do the creation, default all the fields, and hook the service to the Car. this simplifies the call site, and is especially useful if there are several points in your app where you add services to a car. hope some of this helps, DMG
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
May ’22