I got it to work.There are some spelling mistakes on the presentation.The objects you pass in need to have the type [[String : Any]]So you basically have have key value pairs in a list. The strings must match the attribute names in your core data model.Also you need to cast the insertResult to NSBatchInsertResult. Not NSBatchInsertRequest.I used an example entity CDTest with the attributes "id" of type Int32 and "name" of type string. I made "id" the constraint.The following code worked for me then:class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.batchInsertExamples()
}
func batchInsertExamples() {
var objectsToInsert: [[String : Any]] = []
for i in 0...5 {
objectsToInsert.append(["id" : i, "name" : "My Name"])
}
self.persistentContainer.viewContext.performAndWait {
do {
let insertRequest = NSBatchInsertRequest(entity: CDTest.entity(), objects: objectsToInsert)
let insertResult = try self.persistentContainer.viewContext.execute(insertRequest) as! NSBatchInsertResult
let success = insertResult.result as! Bool
if !success {
print("batch insert was not successful")
}
} catch {
print(error.localizedDescription)
}
if self.persistentContainer.viewContext.hasChanges {
do {
try self.persistentContainer.viewContext.save()
} catch {
print("Error: \(error)\nCould not save Core Data context.")
return
}
}
}
}
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "nsbatchinsert")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
container.viewContext.automaticallyMergesChangesFromParent = true
container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
container.viewContext.undoManager = nil
container.viewContext.shouldDeleteInaccessibleFaults = true
})
return container
}()
}
Post
Replies
Boosts
Views
Activity
check my answer to this post: https://forums.developer.apple.com/thread/125374
Looks like your self.sectionCustomers = self.orderCustomersIntoSections() call is missing after you load from your file.I guess it depends on the amount of data you are storing. Saving to a file works fine. You can also use a database.
You are checking against a certain date with time. There most likely is no set of data for that moment. You should use a date range. So something like "startDate > %@ AND startDate < %@".Also check out this function in HKQuery. That's basically what you wantopen class func predicateForSamples(withStart startDate: Date?, end endDate: Date?, options: HKQueryOptions = []) -> NSPredicate
Well a certain date is also a date range. Let’s say you want everything on the 18th of April 2020, then you check against >= 18th of April at 00:00 and < 19th of April at 00:00. You can also use smaller ranges, like hours or minutes. I don’t think it makes any sense to go even smaller than minutes. Your taken steps are saved with date and time. If you just check for "date == 18th of April” there will still be some time where you probably won’t have any data for.
Derived attributes can't be used for unique constraints.You will get the following error:Failed to parse model XML with failure reason Property type is not valid for unique constraints.
You could just add a 'name_lowercased' attribute to your data model and make this your unique constraint instead. You can fill your object property with your 'name' and a .lowercased() call then.After all the name "aPpleS" is different from "Apples".If you really don't want that, there also is the option to implement your own MergePolicy, but that seems to be too much for your case.
Sounds like you need to implement a new model version if it crashes. See:https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreDataVersioning/Articles/Introduction.html
Is your function "reloadTableData()" called if you search?In general I would not check in every function if user is filtering and then access different lists.I would always use self.filteredSectionCustomers and make sure, that if there is nothing in the search field, to simply copy your self.sectionCustomers to self.filteredSectionCustomers. This way self.filteredSectionCustomers is always correct filled. If you change self.filteredSectionCustomers you will also have to reload your tableview
My swift version looks like this:let today = Calendar.current.startOfDay(for: Date())
let tomorrow = Calendar.current.nextDate(after: today, matching: DateComponents(hour: 0), matchingPolicy: .nextTimePreservingSmallerComponents) ?? Date()
let predicate = NSPredicate(format: "startDate >= %@ AND startDate < %@", today as NSDate, tomorrow as NSDate)
If you are comparing against > previous day and < next day, it's perfectly correct to show the total of today and previous day. Because it includes the times. if your previous day is set to 0:00 and you check against > 0:00 then 0:01 already qualifies. Thats still data for yesterday, but thats what you asked for in your predicate. Please see my previous answer again. You first need to start of the day for today. Then startDate needs to be bigger or equal to that and smaller to start of next day. So if you want everything for today, you need:today at 00:00 <= startDate < tomorrow at 00:00
Check out HKObserverQuery
You are welcome. It would be nice to chose an accepted answer to mark your original question as answered.
Just to be sure, you did set the "Push Notifications" capability in your macOS app?
Sorry, I have no experience with obj c."The way i plan to implement is to just observe if there are any changes. If there are then run the original query to retrieve those changes."That's exactly what HKObserverQuery does. See documentation: https://developer.apple.com/documentation/healthkit/hkobserverquery/executing_observer_queries-> "The observer query’s update handler does not receive any information about the change—just that a change occurred. You must execute another query, for example an HKSampleQuery or HKAnchoredObjectQuery, to access the changes."