Search code examples
core-datansarraycontrollernsorderedset

Custom NSManagedObject classes to add/remove Object from NSOrderedSet


I'm learning Cocoa and following an example in Aaron Hillegass's book (Chapter 32 Core Data Relationships) and can't get it working for my own app.

I have a core data model that consists of a parent object with a to-many relationship to children but mine is an ordered set unlike in the book which is a basic NSMutableSet.

Each of the objects, parent and child, have associated NSArrayControllers and I've developed a document-based app in the Interface Builder with buttons and bindings that add/remove child objects (called perceptrons in my case) from the selected parent (called a layer). That's all working.

Now I want to intercept the add and remove methods so that I can do my own coding things whenever a child is added or removed.

In the Hillegass book he does this by creating the NSManagedObjects subclasses and then implementing addEmployeesObject: and removeEmployeesObject: methods in the code. So that's what I tried.

Here is my child subclass created by the XCode Editor:

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@class Network, Perceptron;

@interface Layer : NSManagedObject

@property (nonatomic, retain) Network *network;
@property (nonatomic, retain) NSOrderedSet *perceptrons;
@end

@interface Layer (CoreDataGeneratedAccessors)

- (void)insertObject:(Perceptron *)value inPerceptronsAtIndex:(NSUInteger)idx;
- (void)removeObjectFromPerceptronsAtIndex:(NSUInteger)idx;
- (void)insertPerceptrons:(NSArray *)value atIndexes:(NSIndexSet *)indexes;
- (void)removePerceptronsAtIndexes:(NSIndexSet *)indexes;
- (void)replaceObjectInPerceptronsAtIndex:(NSUInteger)idx withObject:(Perceptron *)value;
- (void)replacePerceptronsAtIndexes:(NSIndexSet *)indexes withPerceptrons:(NSArray *)values;
- (void)addPerceptronsObject:(Perceptron *)value;
- (void)removePerceptronsObject:(Perceptron *)value;
- (void)addPerceptrons:(NSOrderedSet *)values;
- (void)removePerceptrons:(NSOrderedSet *)values;
@end

And here are the two methods I implemented in Layer.m as per the text book:

- (void)addPerceptronsObject:(Perceptron *)value
{
    NSLog(@"Network '%@' layer %lu is adding perceptron %lu", [[self network] name], [self indexInNetwork], [value indexInLayer]);
    NSSet *s = [NSSet setWithObject:value];
    [self willChangeValueForKey:@"perceptrons"
                withSetMutation:NSKeyValueUnionSetMutation
                   usingObjects:s];
    [[self primitiveValueForKey:@"perceptrons"] addObject:value];
    [self didChangeValueForKey:@"perceptrons"
     withSetMutation:NSKeyValueUnionSetMutation
                  usingObjects:s];
}

- (void)removePerceptronsObject:(Perceptron *)value
{
    NSLog(@"Network '%@' layer %lu is removing perceptron %lu", [[self network] name], [self indexInNetwork], [value indexInLayer]);
    NSSet *s = [NSSet setWithObject:value];
    [self willChangeValueForKey:@"perceptrons"
                withSetMutation:NSKeyValueUnionSetMutation
                   usingObjects:s];
    [[self primitiveValueForKey:@"perceptrons"] removeObject:value];
    [self didChangeValueForKey:@"perceptrons"
               withSetMutation:NSKeyValueUnionSetMutation
                  usingObjects:s];
}

I put NSLogs in so I'm sure they are not getting called - nothing in the console when I add/remove perceptron objects.

What does the ArrayController do when it gets an add: remove: message? Is it sending addObject/removeObject messages directly to the set? Why in the textbook example does it send a message up to the parent object to remove a child? Why is that not happening here? Is there a way to debug this and find out?

thanks


Solution

  • Bill,

    You are overriding methods that are dynamically generated by Core Data. I suspect your static entries in the lookup table are just being over written. These methods are not the same as the @property methods, which expect to be overridden.

    In a bigger sense, why do you want to insert your code here? There are better supported methods designed for your implementation when objects are instantiated. You may wish to examine -awakeFromFetch and -awakeFromInsert.

    Andrew