I have two NSManagedObject:
DataEntered
Provence
There is a relation between them: DataEntered must have ONE Provence, and Provence may have one/multiple DataEntered.
All is working well, but when using Instruments and Allocations, every time I set the Provence to DataEntered, a new _CDSnapshot_Provence_ appears in #Living:
Provence * provence = [[self fetchedResultsController] objectAtIndexPath:indexPath];
[self.dataEntered setAddress_provence:provence];
The setter for Provence in DataEntered is managed by CoreData, there is no customization.
When I save DataEntered, is saved correctly. What can cause the creation of multiple living _CDSnapshot_Provence_ ?
Thanks!
#class Provence;
#interface DataEntered : NSManagedObject
#property (nonatomic, retain) NSString * name;
#property (nonatomic, strong) Provence *address_provence;
#end
#class Provence;
#interface DataEntered : NSManagedObject
#property (nonatomic, retain) NSString * name;
#property (nonatomic, strong) Provence *address_provence;
#end
#class DataEntered;
#interface Provence : NSManagedObject
#property (nonatomic, retain) NSString * name;
#property (nonatomic, retain) NSSet *dataEnteredAddress_Provence;
#end
#interface Provence (CoreDataGeneratedAccessors)
- (void)addDataEnteredAddress_ProvenceObject:(DataEntered *)value;
- (void)removeDataEnteredAddress_ProvenceObject:(DataEntered *)value;
- (void)addDataEnteredAddress_Provence:(NSSet *)values;
- (void)removeDataEnteredAddress_Provence:(NSSet *)values;
#end
#import "Provence.h"
#import "DataEntered.h"
#implementation Provence
#dynamic name;
#dynamic dataEnteredAddress_Provence;
#end
I saw exactly the same thing and I believe that this is to be expected.
See the section Conflict Detection and Optimistic Locking in the Apple docs at
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdChangeManagement.html
"When Core Data fetches an object from a persistent store, it takes a snapshot of its state. A snapshot is a dictionary of an object’s persistent properties—typically all its attributes and the global IDs of any objects to which it has a to-one relationship."
There is also a section at that same link that is useful to read - Snapshot Management
The problem I ran into was getting Core Data to release its memory allocations after I had faulted all the managed objects or did a context reset.
I just published a blog posting on this and related topics:
Core Data issues with memory allocation - http://finalize.com/2013/01/04/core-data-issues-with-memory-allocation/
Hope this helps.
Scott
Related
I have two entities and have just created a 1:1 relationship between them. There are subclasses for the entities but they have a lot of code in them at this point so I don't want to use Xcode to automatically generate new NSManagedObject subclasses.
Instead, I thought I could just reference the relationship with a property in each one. I did that and it seemed to work for a while but now it is throwing mysterious errors and I can't seem to get rid of them. I have imported the reciprocal of each one but it is not helping. Can anyone recommend what I should do? Many thanks in advance.
Subclassed NSManagedObjects (simplified)
//Items.h
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#import "Notes.h"
#interface Items : NSManagedObject
#property (nonatomic, retain) NSNumber *iid;
#property (nonatomic, retain) NSString *item;
//this is relationship
#property (nonatomic, retain) Notes *note;
//above throws error Unkown Type Name 'Notes'
#end
//Notes.h
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#import "Items.h"
#interface Notes : NSManagedObject
#property (nonatomic, retain) NSNumber * nid;
#property (nonatomic, retain) NSString * note;
//this is relationship
#property (nonatomic, retain) Items *item;
//above throws error Unkown Type Name 'Item'
#end
This is similar to relationship
In Objective-C you can't use a type before it is declared. To fix this you can use a forward declaration of your classes by putting these lines below the #import statements and above the first #interface.
#class Items;
#class Notes;
If your posted code is not representative of your actual file structure (which I assume it isn't), you'll have to put the #class statement for Items in the Notes.h file and the #class statement for Notes in the Items.h file.
I'm trying to add a field to an entity and whenever I try to access the new field I get
unrecognized selector sent to instance...
Everything else about the entity works. I'm able to add objects and I'm able to assign values to other fields in the object, but not to the new objects.
Of note, I also deleted the DerivedData directory and I deleted the .mom/.momd files to make sure the tables are being built correctly.
Any thoughts?
Locations.h
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#class Games, Players;
#interface Locations : NSManagedObject
#property (nonatomic, retain) NSNumber * defaultLoc;
#property (nonatomic, retain) NSString * locationAddr1;
#property (nonatomic, retain) NSString * locationAddr2;
#property (nonatomic, retain) NSString * locationCity;
#property (nonatomic, retain) NSNumber * locationID;
#property (nonatomic, retain) NSString * locationName;
#property (nonatomic, retain) NSString * locationState;
#property (nonatomic, retain) NSString * locationZip;
#property (nonatomic, retain) NSNumber * numberOfCourts;
#property (nonatomic, retain) NSNumber * defLoc;
#property (nonatomic, retain) NSSet *haveGames;
#property (nonatomic, retain) NSSet *havePlayers;
#end
#interface Locations (CoreDataGeneratedAccessors)
- (void)addHaveGamesObject:(Games *)value;
- (void)removeHaveGamesObject:(Games *)value;
- (void)addHaveGames:(NSSet *)values;
- (void)removeHaveGames:(NSSet *)values;
- (void)addHavePlayersObject:(Players *)value;
- (void)removeHavePlayersObject:(Players *)value;
- (void)addHavePlayers:(NSSet *)values;
- (void)removeHavePlayers:(NSSet *)values;
#end
Locations.m
#import "Locations.h"
#import "Games.h"
#import "Players.h"
#implementation Locations
#dynamic defaultLoc;
#dynamic locationAddr1;
#dynamic locationAddr2;
#dynamic locationCity;
#dynamic locationID;
#dynamic locationName;
#dynamic locationState;
#dynamic locationZip;
#dynamic numberOfCourts;
#dynamic defLoc;
#dynamic haveGames;
#dynamic havePlayers;
#end
Note: defLoc and defaultLoc are two fields that I added. These are the ones giving me problems.
Executing code:
- (IBAction)updateLocation:(UIStoryboardSegue *)segue
{
// If it is not "Edit" it is an "Add" and we need to insert a newobject.
if ([segueType1 isEqualToString:#"Add"])
{
NSManagedObjectContext *context = [[self fetchedResultsController] managedObjectContext];
location = [NSEntityDescription insertNewObjectForEntityForName:#"Locations" inManagedObjectContext:context];
}
location.locationName = lName;
location.locationAddr1 = lAddr1;
location.locationAddr2 = lAddr2;
location.locationCity = lCity;
location.locationState = lState;
location.locationZip = lZip;
location.numberOfCourts = lNumCourts;
location.defLoc = lNumCourts;
// location.defaultLoc = [NSNumber numberWithInt:1];
// DLog(#"ldefaultLocation = %#",ldefaultLocation);
location.defaultLoc = ldefaultLocation;
segueType1 = #"Add"; // Always reset back to Add so that segues work right
}
location.defLoc above is the command that gives the error...All other location statements work fine.
That can happen when you don't declare the new attribute in your NSManagedObject child. As soon as you add a new field in the core data model, remember to add the right property to the NSManagedObject class and declare it #dynamic in the implementation.
I got few entities for an iOS App which are linked by relations. To make a simple example, lets assume we got a relation like this (one-to-many):
company <--->> person
I'm using xcode 4.6 and the core data modelling tool for model generation, so I end up with
//Company.h
#class Person;
#interface Company : NSManagedObject
#property (nonatomic, retain) NSString * company_name;
#property (nonatomic, retain) NSNumber *has_changed;
#property (nonatomic, retain) NSSet *person;
#end
#interface Company (CoreDataGeneratedAccessors)
- (void)addPersonObject:(Person *)value;
- (void)removePersonObject:(Person *)value;
- (void)addPerson:(NSSet *)values;
- (void)removePerson:(NSSet *)values;
#end
//Company.m
#import "Company.h"
#import "Person.h"
#implementation Company
#dynamic company_name;
#dynamic has_changed;
#dynamic person;
#end
And
//Person.h
#class Company;
#interface Person : NSManagedObject
#property (nonatomic, retain) NSString * first_name;
#property (nonatomic, retain) NSString * last_name;
#property (nonatomic, retain) Company *company;
#end
//Person.m
#import "Person.h"
#import "Company.h"
#implementation Person
#dynamic first_name;
#dynamic last_name;
#dynamic company;
#end
Now, suppose I want to set the boolean (implemented as NSNumber in Core Data) attribute has_changed to TRUE every time one of the following occurs:
a attribute of the company entity is changed, except the has_changed attribute itself of course (since this would cause a loop)
a attribute of the person entity is changed
What would be the best (easy to implement + fast to process) way to implement something like this? For what I was able to find out, is that there are two options:
Key value observing (KVO)
custom method accessors
However, everything I find related to this topic seems to be outdated because of the changes in objective-c 2.0, core-data / cocoa or iOS. For example, automatically generating the accessor methods by using the core-data modelling editor dosn't seem to work when using xcode 4.6 with ARC enabled, since everything I get pasted are the #dynamic lines which core-data generates anyways (see code example above).
Also I find it a bit confusing what the documentation says. What would be the best way to implement this? KVO? Custom accessors? Bit of both or even something compleatly different? And how would a possible implementation look like for the given example?
You could do this as such:
#implementation Company
// ...
- (void) didChangeValueForKey: (NSString *) key
{
[super didChangeValueForKey: key];
if (! [key isEqualToString: #"has_changed"])
self.has_changed = YES;
}
// ...
#end
and similar for Person though the company property. You'd also want to implement didChangeValueForKey:withSetMutation:usingObjects:
Note that this suggestion does not address the common need of having a controller know about a change. There are other ways to do that.
I am using RestKit 0.20 to map 2 entities.There is a one to many relationship.
Teacher<->>SchoolClass
Here is the Teacher.h
#class SchoolClass;
#interface Teacher : NSManagedObject
#property (nonatomic, retain) NSString * firstName;
#property (nonatomic, retain) NSString * lastName;
#property (nonatomic, retain) NSNumber * teacherId;
#property (nonatomic, retain) NSSet *teachesClass;
#end
#interface Teacher (CoreDataGeneratedAccessors)
- (void)addTeachesClassObject:(SchoolClass *)value;
- (void)removeTeachesClassObject:(SchoolClass *)value;
- (void)addTeachesClass:(NSSet *)values;
- (void)removeTeachesClass:(NSSet *)values;
#end
Here is the SchoolClass.h
#interface SchoolClass : NSManagedObject
#property (nonatomic, retain) NSString * classCodeId;
#property (nonatomic, retain) NSString * classDesc;
#property (nonatomic, retain) NSString * classRoom;
#property (nonatomic, retain) Teacher *classTeacher;
#end
The code for the relationship mapping is:
[classMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"teacher" toKeyPath:#"classTeacher" withMapping:teacherMapping]];
The results are that in the SchoolClass objects, the classTeacher properties are correctly added. However in the Teacher objects, the teachesClass properties are all empty. Is this expected behavior or I missed something?
Thanks
Ray
Somehow the problem is gone now. All the relationships now working fine. Not sure exactly what happened. Perhaps because I did a reset for the simulator after made a json change. Previously the json results had a problem that caused both side of the relationship problems. After it was fixed, the SchoolClass objects were fine but Teacher objects had relation problems. Now both are fine.
I need to add a CLRegion to my Core Data Entity but I don't what type to select for it.
I read this doc but I'm still confused on how to get it setup correctly. If someone could provide an explanation I'd reall appreciate it.
For the entity attributes type for the CLRegion select "Transformable" Then define what the object is in the the NSManagedObject that Core Data generates for you. (see location below)
#interface Person : NSManagedObject
{
}
#property (nonatomic, retain) NSString * firstName;
#property (nonatomic, retain) NSString * lastName;
#property (nonatomic, retain) CLRegion * location;
#end
#implementation Person
#dynamic firstName;
#dynamic lastName;
#dynamic location;
#end