IOS (7)

About NSObjectID

Once you save, you get a persistent object ID… unless you are not connected directly to a PSC, and have a parent MOC instead. Basically, you only get a persistent object ID when saving from a MOC directly connected to a PSC. However, you can convert into a persistent object ID anytime you want with the NSManagedObjectContext method

- (BOOL)obtainPermanentIDsForObjects:(NSArray *)objects
                               error:(NSError **)error;
Copy the code

Edit

First, if your code depends on knowing if an object ID is temporary or not, you should rethink you logic… this does not sound right, unless you are writing some special core data code. Second, if your MOC has a PSC and not a parent MOC, you must be querying the objectID and it’s temp/perm status before the context is saved. Why don’t you do something like this where you save the context…

NSLog(@"before save: %@", [moc registeredObjects]);
BOOL result = [moc save:&error];
NSLog(@"after save: %@", [moc registeredObjects]);
Copy the code

and you will see the IDs of all objects… you can visually distinguish between the ones that are temporary and the ones that are permanent. The temporary ones look like this…

<NSManagedObject: 0x7f8834836e10> (
  entity: Foo;
  id: 0x7f8834836e70 <x-coredata:///Foo/tECDD46E2-3D01-4E5D-BCE8-1DD8DB2138A512>;
  data: { identifier = 8; }),
Copy the code

The permanent ones look like this…

<NSManagedObject: 0x7f8834836e10> (
  entity: Foo;
  id: 0x7f8834c231e0 <x-coredata://38B5921E-4638-42FD-AD94-78555561DBA7/Foo/p2>;
  data: { identifier = 8; }),
Copy the code

After the save, all objects should have permanent IDs.

Remember, the FRC will get updates anytime the MOC changes, and not just when a save occurs. The exception you reference at the end of your question looks like a bad indexPath.

Optimizations for Core Data

The Entity class:

#import "Entity.h"
@implementation Entity
@dynamic name;
@dynamic orgName;
@dynamic jobTitle;
@dynamic school;
-(void)awakeFromFetch{
    [super awakeFromFetch];
    NSLog(@"awakeFromFetch");
}
@end


//    self.managedObjectContext.stalenessInterval=0;
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Entity" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];
    NSError *error = nil;
    NSArray *fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
    Entity* e=fetchedObjects.lastObject;
    NSLog(@"%@",e.name);
    [self.managedObjectContext refreshObject:fetchedObjects.lastObject mergeChanges:YES];
    NSLog(@"%@",e.name);
Copy the code

Student* s= fetch from MOC s.name=@”8888″ // Fetch the same object Student* s= fetch from MOC MOC s.name is still @”8888″ Birch Sinkwater -iOS(903102) 17:21:31 is the property was rolled back. My question is that since the state of the object has not changed, why did the second fetch execute the SQL query birch Chenhai – IOS() 17:22:26 SQL query because he did not know whether it was the same object before the query? -iOS() 17:24:02 CoreData does cache data if you don’t let him query it. The CoreData data is fully synchronized with the contents of the database… This is obviously optimization… 17:24:53 Yes, to synchronize, you have to force it to become Fault birch sink -iOS() 17:25:20 change it to Fault will not synchronize birch sink -iOS() 17:25:25 ? Shanghai – Laotan Sauerkraut -IOS() 17:25:38 Why not? -iOS() 17:25:49 need to call save to save it in database? Don’t know Shanghai – old pickled vegetable – IOS () 17:26:36 said in a document, you have to call refreshObject: mergeChanges Shanghai – old pickled vegetable – IOS () 17:26:57 that last parameter to YES, will merge to the object’s changes IOS() 17:27:46 You still use core data well!


NSManagedObjectContext: undo save-operation?

Could you use a child managed object context to do your save (which pushes it up to the parent, but doesn’t touch the file on disk), and then do a rollback on the parent if you want to undo it?

I think calling save is like committing all the changes you’ve made since the last save, and rollback is like discarding them. Once you’ve committed the changes, they’re in the persistent store and there’s nothing keeping transaction logs in order to support rolling back.

Can you explain a bit more about why you want a save in the middle of your transaction? Stackoverflow.com/questions/1…


Find the sum of individual attributes

There are two ways to solve this problem: first – get your data to NSSet or NSArray and use @sum operator: Count is an attribute of Pen.

//assume that `pens` are NSArray of Pen
NSNumber *countSum=[pens valueForKeyPath:"@sum.count"];
Copy the code

PerformBlockAndWait thread

PerformBlock: Asynchronously performs a given block on the receiver’s queue.

PerformBlockAndWait: Synchronously performs a given block on the receiver’s queue. When the

[context performBlockAndWait:^{// work on the current thread that called this code, This is also consistent with the following usage rules, that is, once the Manage Object is synchronized, it can be used directly in the corresponding thread.}]Copy the code

Context created with this method:

[[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
Copy the code

Note when using the block above:

Working with Data Between Blocks • ObjectIDs often Useful ■ Rematerialize into MO with objectWithID: ■ objectWithID will reuse cached data Okay to retain MOs but not look or use outside block • use __block variables • Remember NSError are autoreleasedCopy the code

ref:CoreData performBlock


CoreData multithreading principles

Before doing anything concurrent with Core Data, It is important to get the basics right. We strongly recommend reading through Apple’s Concurrency with Core Dataguide. This document lays down the ground rules, Such as never passing managed objects between threads. This doesn’t just mean that you should never modify a managed object object on another thread, but also that you should never read any properties from it. To pass around an object, pass its object ID and retrieve the object from the context associated to the other thread.

Doing concurrent programming with Core Data is simple when you stick to those rules and use the method described in this article.

Managed Objects can be written or read only in the thread where the CORRESPONDING MOC resides. If you want to operate on another thread, you need to pass the Object ID in a different thread.


Child context and parent Context for Core Data

Finally, there is a lot of noise about child contexts these days. Our advice is not to use them for background operations. If you create a background context as a child of the main context, saving the background context will still block the main threada lot. If you create the main context as a child of a background context, You actually don’t gain anything compared to a more traditional setup with two independent contexts, because you still have to merge the changes from the background to the main context manually.

When the main context is used as the parent context, the main thread is blocked when the background context is saved.

The setup with one persistent store coordinator and two independent contexts is the proven way of doing core data in the background. Stick with it unless you have really good reasons not to.

Rotation of UIBezierPath 1. There is nothing called a path