With CBDCoreDataToolKit, you can clone, replace or import your NSManagedObject
s. Cloning is useful when you want to transfer new data from a NSManagedObjectContext
(a MOC
) to another one. Importing is when you want to "integrate" some data to one MOC
to another one. By integrating, I mean that the data to import is not entirely new. Maybe there are just new links between entities, or maybe there is just a new instance of some entity with plenty of relationships with already existing objects.
One has to understand that in such a case:
-
cloning will "pull" the entire graph connected to this new object, and we will have plenty of duplicates.
-
importing is much more clever (and difficult) and will "pull" the entire graph connected to this new object and will merge it with the already existing graph. This is great!
You want to copy an object (and all the graph associated to it) from a MOC
to another one. CBDCoreDataToolKit can do it. It will also copy the objects in relationship with the first object (and recursively), but you can specify entities or attributes to ignore.
Let's say you have a graph with many objects in relation one with another. You want to replace one object in this graph by another one, and of course, you want the graph to stay the same. CBDCoreDataToolKit can do it. When you don't have to ask yourself questions about MOC
s: you take any NSManagedObject
and you replace it by any other one.
It's a little bit like cloning but it's more powerful. While cloning was pulling all the graph (excepted some parts you can cut off) of an object from a sourceMOC
to a targetMOC
, the importing feature is more clever.
To import some data, it's easy!
First, you have to create an instance of CBDCoreDataImporter
. You do:
CBDCoreDataImporter *myImporter;
myImporter = [CBDCoreDataImporter alloc] initWithSourceMOC:sourceMOC
targetMOC:targetMOC];
And then, to import:
[myDataImporter import:object];
It will import object
to targetMOC
and will include it in the graph of already existing objects of targetMOC
. To do that, CBDCoreDataImporter will have to compare objects in the sourceMOC
and in the targetMOC
. This is the aim of CBDCoreDataDiscriminator
.
An instance of CBDCoreDataDiscriminator
aims at comparing objects of a given entity, regarding given attributes and relationships. Instead of testing the equality with ==
or with isEqual:
, it will use the (given at the initialisation) attributes and relationships.
Some code:
CBDCoreDataDiscriminator *myDiscriminator;
myDiscriminator = [CBDCoreDataDiscriminator alloc] initWithDefaultType];
[myDiscriminator isSourceObject:firstObject
similarToTargetObject:secondObject];
NSArray *similarObjects = [myDiscriminator similarObjectTo:refObject
inMOC:myMOC];
NSManagedObject *similarObject = [myDiscriminator firstSimilarObjectTo:refObject
inMOC:myMOC];
You can also do this kind of actions:
[myDiscriminator objectsInWorkingMOC:MOCWhereWeAreWorking
alreadyExistingInReferenceMOC:referenceMOC];
But, you may want to define very precisely upon which attributes and relationships you want to do all that: discriminating as well as importing. It is possible and it uses CBDCoreDataDecisionCenter
and CBDCoreDataDecisionUnit
.
A CBDCoreDataDecisionUnit
will typically says something like:
-
for the entity
Person
, consider only attributesname
,age
and relationshipsfamily
to make your decision (a decision, here, is either "tell me if they are similar" or "copy this entity", but you can imagine other ones). -
for the entity
Car
, don't (I mean : never) consider the relationshipowners
to make your decision. -
ignore the entity
Bike
. -
etc.
The best is to refer to the documentation to know more about the code.
A CBDCoreDataDecisionCenter
groups together several CBDCoreDataDecisionUnit
. It is the true decision maker, because in the case of an entity Entity
that heritates from an other SuperEntity
, if both entities have decision unit , the decision cannot be taken withour knowing about both.
You don't have to specify a decision unit for all entities.
You can use one the three global settings: initWithFacilitatingType
, initWithSemiFacilitatingType
, initWithDemandingType
. There are all conveninent. See the doc for more information.
Here is some code:
CBDCoreDataDecisionCenter *myDecisionCenter;
myDecisionCenter = [CBDCoreDataDecisionCenter alloc] initWithSemiFacilitatingType];
CBDCoreDataDecisionUnit *myUnit1;
myUnit1 = [[CBDCoreDataDecisionUnit alloc] initForEntity:personEntity
usingAttributes:nil
andRelationships:@[@"friends"]];
CBDCoreDataDecisionUnit *myUnit2;
myUnit2 = [[CBDCoreDataDecisionUnit alloc] initForEntity:employeeEntity
usingAttributes:nil
andRelationships:@[@"employees"]];
[myDecisionCenter addDecisionUnit:myUnit1];
[myDecisionCenter addDecisionUnit:myUnit2];
[myDecisionCenter relationshipsFor:employeeEntity]
With CoreData, when you wanna fetch, it's long and repetitive. CBDCoreDataToolKit offers you convenience methods to go to the point. These methods accepts format strings, so it is even more convenient. Many other librairies do the same, including the very well known Magical Record. Unfortunately, Magical Record does not work with NSPersistentDocument
. CBDCoreDataToolKit does.
All the methods defined in categories over Apple classes are suffixed with _cbd_
to avoid name conflicts.
You can fetch on subclasses of NSManagedObject
, if they implement the class method + (NSString *)entityName
or if they are have the same name as their corresponding entity. This is the case for classes generated by mogenerator
.
You will able to do, for example
[Person findInMOC:self.myMOC
orderedBy:@"name, age"
withPredicateFormat_cbd_:@"city == %@", theCity];
Some of the methods in the categories over NSManagedObject+CBDActiveRecord
require one or the other of the following conditions:
- you have generated your subclasses of
NSManagedObject
withmogenerator
. - the subclass of
NSManagedObject
corresponding to yourEntity
is also nammedEntity
.
But don't worry, this requirement (which is always satisfied actually) has been limited to only this category. All the rest of this pod doesn't ask for this requirement.
The documentation of classes and methods is available here.
To run the example project; clone the repo, and run pod install
from the Example directory first.
CBDCoreDataToolKit is available through CocoaPods, to install it simply add the following line to your Podfile:
pod "CBDCoreDataToolKit"
Colas Bardavid
- Víctor Pena Placer for his VPPCoreData package
- user353759 of StackOverflow
- 2016/11/30 (v3.3.1):
- Making the
.podspec
compatible with the version 1.0 of Cocoapods - Cleaning up the code
- Making the
- 2014/05/06 (v3.0.0):
- New
@return
for the-clone...
method for arrays of objects: it returns now a dictionary mapping the old objects to the new ones - New convenience initializers for
CBDCoreDataDecisionUnit
- New methods for finding duplicate between two
MOC
s - Correction of various bugs
- No more
- removeLastHint
,removeLastEntryOfTheCache
methods - Add the
ConnectedEntities
sub-library. - Fix a bug on
allObject_cbd_
andcountAllObjects_cbd_
: it was counting several times belonging to several entities (when an entity has a subentity)
- New
- 2014/02/18 (v2.0.0):
- Introducing the much more hi-tech importer from a
MOC
to anotherMOC
. Comparing objects on their graph-like identity.. - New methods for fetching similar objects.
- Slight changes in the names of few methods.
- Introducing the much more hi-tech importer from a
- 2014/02/11 (v1.0.0): New methods. Few changes in the names of few methods.
- 2014/02/11 (v0.0.2): Improved documentation.
- 2014/02/10 (v0.0.1): First release.
Copyright (c) 2014-2016 Colas Bardavid
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.