views:

32

answers:

1

I have come across an interesting conundrum (of course, I could just being doing something horribly wrong).

I would like an NSTokenField to "represent" a relationship in a Core Data Application. The premise is such: You click on a Note from a TableView (loaded from the Notes Array Controller). The token field is then bound (through "value") to the Notes Array Controller selection.Tags. Tags is a to-many relationship on the entity Notes.

Obviously, an NSTokenField will not accept the NSSet that the Array Controller Provides it. To get around this, I subclassed NSTokenFieldCell and overrode its objectValue and setObjectValue: methods. I thought that I could simply translate the NSSet that was being provided to the NSArray that the NSTokenFieldCell expected. (Note: I originally tried overriding these methods on a NSTokenField subclass; however, they were not being called.)

So, I came up with said code:

- (void)setObjectValue:(NSSet*)object {
    tagsList = [object copy];
    NSMutableArray *displayList = [[NSMutableArray alloc] init];
    for (id newObject in tagsList) {
        [displayList addObject:[newObject valueForKey:@"Name"]];
    }
    [super setObjectValue:displayList];
}

- (id)objectValue {
    NSArray *displayList = [super objectValue];
    NSEntityDescription *tagEntity = [NSEntityDescription 
                               entityForName:@"Tag" 
                               inManagedObjectContext:[appDelegate 
                                                       managedObjectContext]];
    NSMutableSet *returnValue = [[NSMutableSet alloc] init];
    for (NSString *token in displayList) {
        NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
        [request setEntity:tagEntity];

        NSPredicate *predicate = [NSPredicate predicateWithFormat:
                                  @"Name == %@", token];
        [request setPredicate:predicate];

        NSError *error;
        NSArray *results = [[appDelegate managedObjectContext] executeFetchRequest:request error:&error];
        if (results == nil) {
            NSManagedObject *object = [NSEntityDescription insertNewObjectForEntityForName:@"Tag" inManagedObjectContext:[appDelegate managedObjectContext]];
            [object setValue:token forKey:@"Name"];
            [returnValue addObject:object];
        } else {
            [returnValue addObject:[results objectAtIndex:0]];
        }
    }
    return returnValue;
}

It crashes. :( And, surprisingly it crashes on the line that calls [super objectValue]. It gives me the error:

-[NSConcreteAttributedString countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance ...

Sigh. The sad thing is that when I go into the Core Data XML file and give the Note a Tag, it displays correctly, and [super setObjectValue:] is passed an array of strings. However, as soon as I enter something else and mouse away, I get the error.

I am not sure what to do about this. Can anyone spot anything horribly wrong with this? Thanks.

UPDATE: If it makes a difference, I do not have a delegate configured for the TokenField.

A: 

In typical SO fashion, I found the answer to my own question. It was silly to begin with. I simply needed another ArrayController bound to the Notes selection.Tags set. Then, I bound the NSTokenField to the ArrangedObjects of that Controller, implemented some delegate methods. Boom. Simple.

Silly me.

huntaub