views:

162

answers:

1

Before working with Objective-C and Core Data, I had occasions to create classes that needed to be initialized with certain parameters that, after initialization, could not be modified (though they could be read).

With Core Data, I believe I can create a customized init on my NSManagedObject derived class as long as it includes a way to insert the object into a context like such:

-(Cell*) initWithOwner:(CellList*)ownerCellList andLocation:(int)initLocation
{
    if (self = (Cell*) [NSEntityDescription insertNewObjectForEntityForName:@"Cell"
                        inManagedObjectContext:[ownerCellList managedObjectContext]])
    {
        self.location = [NSNumber numberWithInt:initLocation];
        self.owner = ownerCellList;
        [ownerCellList addCellListObject:self];
    }
    return self;
}

Normally, I'd have a location variable and the location property would be read-only (so once set at initialization, it could not be changed). Is there a way to get this sort of pattern with Core Data? Is there a better way I'm not thinking of?

Thanks!

A: 

You are correct. As long as your initializer calls the NSManagedObject's designated initializer, your approach is fine. You can also override the -[NSManagedObject awakeFromInsert] to perform some action after insertion (creation) or -[NSManagedObject awakeFromFetch] to perform an action (e.g. populating a cache) each time the object is faulted back into a managed object context.

Like the rest of Objective-C, there is no way to make a property truly readonly. Malicious code will likely be able to modify your property. However, in your custom class, you can declare a @property(readonly) for e.g. location. This will at least cause a warning if you try to modify the property and will signal your intent to client code.

Barry Wark
Hmmm... just had another thought/question: With the above init function, I would need to do an [[Cell alloc] initWith...] since it's not a class-level function. Isn't that wrong to do with a Core Data object that's auto-released? Would it be more appropriate to replace the initWith... function with a class-level function like createNewCellWithOwner:(CellList*)ownerCellList andLocation:(int)initLocation? The call to insertNewObjectForEntityForName creates the new object and doesn't seem to belong in an init routine, right?
FTLPhysicsGuy
I didn't notice that initially. Yes, you're incurring a memory leak (from the initial +alloc) and you will get problems because you're not retaining the result of -insertNewObject...I would use self = [self initWithEntity:entity inManagedObjectContext:[ownerCellIst managedObjectContext]] instead.
Barry Wark