Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

GorillaPaws

macrumors 6502a
Original poster
Oct 26, 2003
932
8
Richmond, VA
I have controller object that's trying to initialize 2 NSManagedObjects using a custom initialization method and then stick them in an array. When I debug the code, I'm actually getting 2 pointers to the same object so it seems my NSManagedObject subclass is behaving unintentionally like a singleton.

In my custom initialization method, I'm calling the designated initializer (which I haven't overridden) for the NSManagedObject, as the documentation instructs, so I'm not sure why I'm getting 2 references to the same object.

Both tClosetRootNode and tPersonRootNode are pointing to the same memory.
Here is the code that calls the custom Init method:
Code:
//	from DISourceListController.m
-(void) awakeFromNib
{
	//appDelegate is an iVar linked as an IBOutlet in IB.  My core data stack is currently living in the appDelegate
	NSManagedObjectContext *tManagedObjectContext = [appDelegate managedObjectContext];  //  tManagedObjectContext appears valid when debugged
	
	DISourceListNode *tClosetRootNode = [[DISourceListNode alloc] initWithName: @"WARDROBE" 
							      managedObjectContext: tManagedObjectContext
							      childArrayController: closetArrayController];
	DISourceListNode *tPersonRootNode = [[DISourceListNode alloc] initWithName: @"PEOPLE" 
							      managedObjectContext: tManagedObjectContext
							      childArrayController: personArrayController];
	
	rootNodeArray = [[NSArray alloc] initWithObjects: tClosetRootNode,
							  tPersonRootNode, nil];
	[tClosetRootNode release];
	[tPersonRootNode release];	
	
	for( DISourceListNode* tArrayItem in rootNodeArray )
	{
		NSLog( @"rootNodeArray item is: %s", [tArrayItem valueForKey: @"name"] );
	}
	
	[sourceList reloadData];
}

and here is the init method's code:
Code:
//	from DISourceListNode.m
-(id) initWithName: (NSString *)theName managedObjectContext: theMOC childArrayController: (NSArrayController *)theArrayController
{
	NSEntityDescription* tEntityDescription = [NSEntityDescription entityForName: @"DISourceListNode"
							      inManagedObjectContext: theMOC];
	//	Call the Designated initializer with the appropriate Parameters
	[self initWithEntity: tEntityDescription insertIntoManagedObjectContext: theMOC];
	
	//	prep the ivars
	[self setValue: YES forKey: @"isRoot"];
	[self setValue: theName forKey: @"name"];
	[self setChildArrayController: theArrayController];
	[self createChildMArrayWithChildArrayController: theArrayController];
	
	NSLog( @"creating DISourceListNode with name: %@", [self valueForKey: @"name"] );
    return self;
}

Eventually I intend to have more than just these two objects (but I'm trying to get it working first with just these).

I appreciate any help you can send my way, and I'd be happy to post the full project if you think it would help, although it's still pretty rough.
 

kainjow

Moderator emeritus
Jun 15, 2000
7,958
7
Just a wild guess since I haven't done Core Data in about 3 years, but when you call initWithEntity:insertIntoManagedObjectContext: you should assign the return value to self since it's possible for initializers to return a different object:

Code:
if (self = [self initWithEntity: tEntityDescription insertIntoManagedObjectContext: theMOC]) {
    [self setValue....
}
return self;
 

GorillaPaws

macrumors 6502a
Original poster
Oct 26, 2003
932
8
Richmond, VA
Kainjow, you're the man. I'm getting two objects now--although I've now discovered a bunch of other problems now that my objects are finally initialized properly. Thanks so much for your help!
 

kainjow

Moderator emeritus
Jun 15, 2000
7,958
7
I made a test project to figure out what was going on. Basically, alloc returns the same placeholder object for many built-in classes, and init is what returns the actual new object. So if you don't reassign self to the initialized object, you're still pointing to the alloc'd value which explains why both objects were the same. This basically reconfirms the point that you should always assign self to the initialized value and always use init immediately after alloc.

So the docs are wrong when they say alloc returns "a new instance of the receiver." :)
 

BadWolf13

macrumors 6502
Dec 17, 2009
271
0
Hey guys, I know I'm sort of bringing up and old argument, but my question is somewhat related. I'm going to write a program with core-data, as you guys suggested, and as I see it, it's going to require(or at least should have) a subclass of init. Should I take it from your example, that while the init method for a subclass of NSObject always starts with

Code:
[super init]

an NSManagedObject subclass should always call

Code:
[self initWithEntity:  insertIntoManagedObjectContext: ];

within it's init method?
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.