I have a problem. I'm writing an app that using core data and syncing it through iCloud. Should I need to update data in context after receiving changes. Can I discard received changes?
When you get NSPersistentStoreDidImportUbiquitousContentChangesNotification, the incoming changes have already been received and saved to your persistent store file. What you do next is up to you.
Should I need to update data in context after receiving changes
If you want your users to see the new changes, then yes. You can do this with mergeChangesFromContextDidSaveNotification:.
Can I discard received changes?
When you get the notification, the changes are already received and saved. You could save different values if you want. You don't get to tell iCloud whether or not to commit the changes though-- they're already there.
What Tom says is true. The changes are already imported into the persistent store file, but they are not merged into the actual PersistentContext, this is what mergeChangesFromContextDidSaveNotification does.
Related
I'm looking for a way (using SuiteScript 2.0) to handle real-time persistent (stored) field updates, where a field might have changed in NetSuite (for example a lead time was just updated), and it doesn't matter if a user saved the change, or some other automated process changed that field. I just want to be able to pick up on that change:
The moment that it's done, and
Without regard for who or what kicked it off (e.g. it could be a person, but it could also be an automated change from a workflow, or a formula on the field itself which pulls values from another field)
Doing some research I found some options that looked somewhat promising at first. One being the afterSubmit event in a client script, and the other being the fieldChanged event. My issue however is, from what I understood those only really seem to be triggered by a user manually going in and making those changes, but this is only one part of the puzzle and doesn't seem to cover changes made outside of the scope of the user making those changes. Is that correct however? Or would one of those events still be able to capture changes done to that field regardless of who (or what) initiated or triggered the change, and right at the moment the change was saved/ persisted to the database?
UserEvents are basically triggers. In their deployment records you can set the context in which they fire so you can get them to fire in all circumstances (called contexts in Netsuite) but one.
That circumstance is User Events are not fired for record saves made in User Event scripts. i.e., if an AfterSubmit UserEvent script loads, changes and saves your record a fresh user event will not be fired.
I am trying to send a message every time a specific Content Part is updated, created or deleted.
When is created or deleted I use the Content Handler: OnCreated and OnRemoving to send the message.
But during the update I need the previous state of the ContentPart and the new Data also.
Thanks.
[Answer]
The answer and comments of Piotr Szmyd lead me to the solve the problem. Read them.
Use OnVersioning / OnVersioned. Those events gets fired whenever a new version of an item is created. You can access old and new versions of a given part then.
To create a managed object in Core Data:
NSManagedObject *aManagedObject = [NSEntityDescription
insertNewObjectForEntityForName:#"Employee"
inManagedObjectContext:aContext];
To delete a managed object, send a message to its managed object context.
[aContext deleteObject:aManagedObject];
That method sends a message to aManagedObject
- (void)prepareForDeletion
Here's my problem. I'm syncing this data with an external database. I have an attribute named "deleted". When an object is first "deleted" I want to set the "deleted" attribute to YES and later sync it to the external database that it is deleted. At some future date, all "deleted"==YES entities will expire and truly be deleted.
In prepareForDeletion I want to test to see if:
dateSynced >= dateModified
dateSynced <= expirationDate
"deleted" == YES
and truly delete the object, else:
dateModified = Now
"deleted" = YES
and make it not delete
Is there a way to make it not delete at this point?
Or, should I not try to use prepareForDeletion to override deleteObject and just create a new method such as obsoleteObject to set "deleted" = YES and dateModified=Now and only use deleteObject for the purge later?
I implemented such a mechanism very recently.
You cannot delay an entity deletion once it has been marked as deleted. It will be deleted the next time the context is saved. You have to rely on something else to keep things in sync.
Here is my solution. I created a persistent log of events, some of those are delete events. When an entity is marked as deleted, I create a corresponding log entry (in another context actually, which is saved before the context where objects are deleted to ensure the log entries are up to date and saved before the actual deletion is performed). The log is processed later and the delete commands issued to the server. If the log is saved but the deleted entities never deleted because of a crash, the next time the application is launched, the log is processed, the entities deleted locally and remotely at the same time and all is well.
Sounds complicated but it isn't in practice.
I think, you can't do that this way. I've done this that way - on object deletion I store it's object id (in my case it's guid stored as file) and on sync I push deletes to server.
I would not recommend doing so, but there is a way to “undelete” an object from Core Data. It is probably not what you want.
Simply calling insert(object) with the object you want to undelete should do the trick. If the object deletion was not saved in the context, you will have to call processPendingChanges() first.
Important: After the undeletion, you’ll also have to set all of the properties of the object and also undelete all the cascade deletions that might have been applied when processing the pending changes (or when the context has been saved).
Bear in mind this is a dangerous thing to do! You should avoid doing it.
I tested the undelete before a save on iOS 10.
I want to add logging capabilities in my Lotus Notes application. Basically I want to be able to log who make the change, when the change is made, and what field(s) is/are changed in a document. What is the best way to do this? I am thinking to also add this at the end of each document so the user knows who make the changes.
OpenNTF has several tools for this purpose that you could use, including Open Audit and Audit Manager.
I've done this before using LotusScript. It's a bit of a pain, but the basic idea is to:
Create an array or new document object within the QueryOpen event, and store the values for all the items in the current document.
In your QuerySave event, compare the values of the current document to the in-memory copy you made, and then log any differences.
You can create a field on the form to write these changes to, and just append to it each time.
Watch out for other event handlers that make changes everytime the document opens, though. You may need to copy original values in the PostOpen event, for example, if you change some fields in the QueryOpen event each time the doc opens, otherwise you'd get false change logs.
Hope this helps!
A "brute force" approach can also work. Every time a document is saved, create a copy of that version to a (separate) database. This will build an audit trail of the documents. The documents can be compared to extract the changes.
There is quite some overhead in this approach, but in my experience it has been worth it. The implementation is simple and all changes are captured without affecting the actual document. All information that is needed is captured and available for (offline) processing.
I have an NSTableView which is populated via a CoreData-backed NSArrayController. Users are able to edit any field they choose within the NSTableView. When they select the rows that they have modified and press a button, the data is sent to a third-party webservice. Provided the webservice accepts the updated values, I want to commit those values to my persistent store. If, however, the webservice returns an error (or simply fails to return), I want the edited fields to revert to their original values.
To complicate matters, I have a number of other editable controls, backed by CoreData, which do not need to resort to this behaviour.
I believe the solution to this problem revolves around the creation of a secondary Managed Object context, which I would use only for values edited within that particular NSTableView. But I'm confused as to how the two MOC would interact with each other.
What's the best solution to this problem?
The easiest solution would be to implement Core Data's undo functionality. That way you make the changes to Core Data but if the server returns the error, you just rollback the changes. See the Core Data docs for details.