Mastering In CoreData (Part 17 Multithreading Concurrency Strategy Context UndoManager)
This part is the continuation of the previous part. It is mandatory to look the temporary problem that we solved using parent child strategy. Now in this part we are going to solve this problem using undo manager . To know what is the temporary change problem please refer to previous part
In part 2 we said
Managed Object Context (MOC)
Managed Object Context provides Caching, Change tracking, Lazy loading, Redo, Undo and validation features
UndoManager provides a simple way to add undo/redo functionality to your managed Object Context. It’s an Instance property of the managed object context.
Download the starter project or delete the application if you follow the tutorials. First comment out these lines as shown in Figure 1.
Understand Undo Manager from Flow Diagram
As you can see in Figure 2 we performed number of tasks to understand how undo manager works
- First, we start/begin undo group to keep track of the changes we will perform. At this point undo manager start tracking changes
- Added User 1 to the managed object context and put it‘s reference to undo stack
- Added User 2 to the managed object context and put it‘s reference to undo stack
- Ended undo group (It’s very important otherwise application will crash)
context.undoto undo changes
- As you can see User 1 and User 2 now deleted and moved it ot the redo stack
- Performing redo User 1 and User 2 now appear
As you can see in Figure 3 we proved flow diagram theory into code
undoManagerinstance property of Managed Object Context. By default, in iOS it’s value is nil
- By calling
beginUndoGrouping, we start tracking objects and group into the undo stack
- Added two users object into the managed object context
endUndoGroupingwill end this group. This is very important
- Finally we looks into the logs by doing undo and redo operation
As you can see no User object was printed after undo operation . By doing redo two user object printed on the console
beginUndoGroupingincrement grouping level to 2 .
Nested Undo Group
Performs the undo operations in the last undo group
As you can see in Figure 4.
undoNestedGroup group undo last group which was when User 2 was added. As you can see we added User on first undo group and User 2 on second or last undo group. By performing
undoNestedGroup it will undo last undo group which was where User2 was added. Now first undo group become the last after calling
undoNestedGroup again it will delete User1 as well as shown in the Figure 4
As you can see in Figure 5 we proved it using code . Performing undo Nested group undo last group.
There are number of things you should know
undo → Closes the top-level undo group if necessary and invokes
undoNestedGroup → Performs the undo operations in the last undo group (whether top-level or nested), recording the operations on the redo stack as a single group
levelsOfUndo: Int →The maximum number of top-level undo groups the receiver holds.
beginUndoGrouping → Marks the beginning of an undo group.
endUndoGrouping → Marks the end of an undo group.
removeAllActions → Clears the undo and redo stacks and re-enables the receiver.
Solve Temporary Change Problem In Application Using Undo Manager
First delete the application and uncomment
viewWillAppear method as shown in Figure 6. To understand the application, project structure and the problem we are going to solve referred to previous part then come again. In previous we solved the temporary changes problem using parent-child strategy , now we are going to solve it using context
As you can see in Figure 7 we did lot of things to setup
- Created custom back button to get the action of back event
- Fetched User data from main singleton Managed Object Context and that directly populating view . Editing in information will update this context objects as well.
- Before fetched we begin
undoManagerto track temporary changes
Now when user tap on back button we did a couple of things as shown in Figure 8
- First we ended the undo group. It’s very important we need to call it before calling
- Finally we discard changes by calling
undomethod it will discard all the changes that was done in the context from the beginning to end of the undo group
Run the application and run the flow which caused temporary changes was saving in database, now the problem is solved using
RollBack Managed Object Context
Removes everything from the undo stack, discards all insertions and deletions, and restores updated objects to their last committed values
Understand Using Flow Diagram
As you can see in Figure 9 after calling
rollback it discarded all temporary changes in the context and moved their state to last committed value which is the same state as of the persistent store. To illustrate this with example first delete the application and comment out
viewwillAppear method on
As you can see in Figure 10 we did number of things
- First, we created User1 and
saveit to the persistent store by calling
savemethod on the context
- Next User 2 and User 3 created on context only. These are the users not in the persistent store yet
- By calling
rollbackit discarded all the temporary changes in the context. As you can see in the logs User 2 and User 3 was deleted since it was not in the persistent store as we said earlier rollback move the context to the last committed value which means the state of the persistent store
- One thing remembered User 1 referenced will not change if you are using in existing UI application will not crash. Since it will not refresh data from a persistent store it’s referenced remain the same . (Important)
Reset Managed Object Context
Returns the context to its base state
Understand Using Flow Diagram
As you can see in the Figure 11 it performs the same thing as the rollback did. We first saved User1 into the persistent store after that we cached User1 in Managed Object Context . Then we temporarily added User2 and User3 which was not in the persistent store yet. After that we called
reset method on the context and it did the same thing as
rollback did,but there was a slightly difference.It again fetched User1 from persistent store that’s why it’s address was changed whereas in rollback User1 address was the same.
As you can see in Figure 12 t we did number of things and delete the application
- First, we created User1 and save it to the persistent store by calling save method on the context
- Next User 2 and User 3 was created on context only. This was the users not in the persistent store yet
- By calling reset it discarded all the temporary changes in the context. As you can see in the logs User 2 and User 3 were deleted since it was not in the persistent store
- One thing remembered User 1 referenced has changed and if you are using in existing UI application will crash. I used rollback screenshot since there is a minor difference. Since it will refreshed data from a persistent store it’s referenced will change.
Note: All the receiver’s managed objects are “forgotten.” If you use this method, you should ensure that you also discard references to any managed objects fetched using the receiver, since they will be invalid afterwards.
Difference Between Reset and RollBack
Delete the application first
Reset : As you can see reference change and data became faulty also. Since it gets data from a persistent store as shown in Figure 13.
Delete the application first
Rollback : Reference is the same and since it didn’t delete cache data. The data still presents in the cache as shown in Figure 14