How to fetch just object IDs but also include the

2020-05-29 04:04发布

问题:

In the CoreData Apple Docs on working in the background, I came across this bit of advice:

For example, you can configure a fetch request to return just object IDs but also include the row data (and update the row cache)—this can be useful if you're just going to pass those object IDs from a background thread to another thread.

I was wondering how you might implement this fetch request? Specifically how to update the row cache.

I think this is how get just the IDs:

NSFetchRequest* request = [NSFetchRequest fetchRequestWithEntityName:@"MyItem"]; // iOS 5 method
request.returnsObjectsAsFaults = YES; 

How do I do the rest?

回答1:

By default, includesPropertyValues is YES, and returnsObjectsAsFaults is also YES.

If you just want to return object IDs, you need to use...

fetchRequest.resultType = NSManagedObjectIDResultType;

However, there are no properties to be fetched, and the row cache will not be populated. You will just get back a bunch of object IDs.

Note, that BY DEFAULT, (resultType == NSManagedObjectResultType), since both includesPropertyValues and returnsObjectsAsFaults are YES, a fetch will return objects as faults (the object ID is accessible), and the row cache will be filled - but the data will not truly be "in memory" because the object is still a fault... but you can still get at its object ID.

All you need to do is then ask the object for its objectID.

All that, I guess, to say that the behavior you are asking for is what you get by default. So, are you having a problem, or is there some reason you think you are NOT getting that behavior?

EDIT

Ummm... I am saying that BY DEFAULT, you are getting what you want. If you just fill out a fetch request, and don't change any of the attributes, returnsObjectsAsFaults is YES -- so objects that are returned to you will be faults. Furthermore, includesPropertyValues is also YES -- so some amount of property data will be available in the row cache.

You can access the objectID property by calling, well, managedObject.objectID.

EDIT

I apologize, because I am obviously not doing a very good job of communicating because this will be the third time I've said the same thing.

When you create a NSFetchRequest, it has several properties that are set by default.

resultType is set to NSManagedObjectResultType by default. That means, unless you change it, it will still be NSManagedObjectResultType. It also means that the array of results that you get from a fetch will contain an array of NSManagedObjects (as opposed to getting back a count, or a dictionary, or ObjectIDs).

returnsObjectsAsFaults is set to YES by default. That means, unless you change it, it will still be YES. It also means that objects that get returned from a fetch will be faults. The NSManagedObject will not be realized with property data. The object will be a fault. It will have enough metadata to know its type, object ID, and some other stuff.

includesPropertyValues is set to YES by default. That means, unless you change it, it will still be YES. It also means that some amount of property data will be fetched into the row cache.

Each NSManagedObject that gets returned from the fetch will:

  1. Have an Object ID
  2. Be a fault, so the data isn't actually loaded fully into memory
  3. Some amount of property data will be in the row cache

This is everything you are asking for. I'm not sure what else I can add (without repeating myself yet again).

Also, note that if you just want object IDs you can set resultType to NSManagedObjectIDResultType.

Directly from the NSFetchRequest documentation...

includesPropertyValues

You can set includesPropertyValues to NO to reduce memory overhead by avoiding creation of objects to represent the property values. You should typically only do so, however, if you are sure that either you will not need the actual property data or you already have the information in the row cache, otherwise you will incur multiple trips to the database.

During a normal fetch (includesPropertyValues is YES), Core Data fetches the object ID and property data for the matching records, fills the row cache with the information, and returns managed object as faults (see returnsObjectsAsFaults). These faults are managed objects, but all of their property data still resides in the row cache until the fault is fired. When the fault is fired, Core Data retrieves the data from the row cache—there is no need to go back to the database.

If includesPropertyValues is NO, then Core Data fetches only the object ID information for the matching records—it does not populate the row cache. Core Data still returns managed objects since it only needs managed object IDs to create faults. However, if you subsequently fire the fault, Core Data looks in the (empty) row cache, doesn't find any data, and then goes back to the store a second time for the data.

and...

returnsObjectsAsFaults

The default value is YES. This setting is not used if the result type (see resultType) is NSManagedObjectIDResultType, as object IDs do not have property values. You can set returnsObjectsAsFaults to NO to gain a performance benefit if you know you will need to access the property values from the returned objects.

By default, when you execute a fetch returnsObjectsAsFaults is YES; Core Data fetches the object data for the matching records, fills the row cache with the information, and returns managed object as faults. These faults are managed objects, but all of their property data resides in the row cache until the fault is fired. When the fault is fired, Core Data retrieves the data from the row cache. Although the overhead for this operation is small, for large datasets it may become non-trivial. If you need to access the property values from the returned objects (for example, if you iterate over all the objects to calculate the average value of a particular attribute), then it is more efficient to set returnsObjectsAsFaults to NO to avoid the additional overhead.



回答2:

Let me explain it the easy way

By default, NSFetchRequest has

resultType: NSManagedObjectResultType

returnsObjectsAsFaults: YES

includesPropertyValues: YES

Here the return object (in memory) only has objectID property, all other properties is empty (This is what called fault)

includesPropertyValues

YES: means the object properties is in the row cache (some special cache of CoreData), so that when you access those properties, CoreData will look for them in the row cache

NO: means there's no row cache, when you access those properties, CoreData will query SQLite again

returnsObjectsAsFaults

YES: allow includesPropertyValues to have effect (means allowing faulting)

NO: return the object wilh all its properties in memory

NOTE: there are 2 kinds of fault : managed object fault and relationship fault

Read more here Faulting Limits the Size of the Object Graph

So in your case, just play with the default