0

I'm implementing a subclass of NSActionCell (inside an NSTableView), and noticing something unusual. If I set a property (isEditing) when a user clicks a cell, the value of that property is lost, because NSCell is released shortly thereafter. I assumed that this was happening because I wasn't handling copying correctly, so I added copyWithZone. Now I am seeing copyWithZone called - but it's called on an unexpected instance - and the property on that instance is NO - the default value. Each time copyWithZone is called, it's called on this same instance.

Can anyone shed a light on this behavior? I'm attaching the subclass in question, and the output I'm getting. Exactly what do I need to do for cell's properties to be retained when the user clicks on different cells?

@interface MyCell : NSActionCell <NSCoding, NSCopying>
{
}

@property (nonatomic, assign) BOOL isEditing;

@end

@implementation MyCell

- (id)init
{
    if ((self = [super init]))
    {
        [self initializeCell];
    }

    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    if ((self = [super initWithCoder:aDecoder]))
    {
        [self initializeCell];

        self.isEditing = [[aDecoder decodeObjectForKey:@"isEditing"] boolValue];
        NSLog(@"initWithCoder %ld %i", (NSInteger)self, self.isEditing);
    }

    return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [super encodeWithCoder: aCoder];
    NSLog(@"encode %i", self.isEditing);

    [aCoder encodeObject:[NSNumber numberWithBool:self.isEditing] forKey:@"isEditing"];
}

- (void)dealloc
{
    NSLog(@"dealloc %ld %i", (NSInteger)self, self.isEditing);
    [super dealloc];
}

- (id)copyWithZone:(NSZone *)zone
{
    MyCell *copy;

    if ((copy = [[MyCell allocWithZone:zone] init]))
    {
        copy.isEditing = self.isEditing;
    }

    NSLog(@"copy %ld %i new: %ld", (NSInteger)self, self.isEditing, (NSInteger)copy);

    return copy;
}

- (void)initializeCell
{
    self.isEditing = NO;
}

- (BOOL)startTrackingAt:(NSPoint)startPoint inView:(NSView *)controlView
{
    return YES;
}

- (void)stopTracking:(NSPoint)lastPoint at:(NSPoint)stopPoint inView:(NSView *)controlView mouseIsUp:(BOOL)flag
{
    if (flag)
    {
        self.isEditing = YES;
        NSLog(@"stopTracking %ld %i", (NSInteger)self, self.isEditing);
    }
}

@end

Output (produced when a user clicks the cell):

2012-11-21 08:17:59.544 SomeApp[2778:303] copy 4310435936 0 new: 4310152512
2012-11-21 08:18:00.136 SomeApp[2778:303] stopTracking 4310152512 1
2012-11-21 08:18:00.136 SomeApp[2778:303] dealloc 4310152512 1

and another click (on a different cell):

2012-11-21 08:19:24.994 SomeApp[2778:303] copy 4310435936 0 new: 4310372672
2012-11-21 08:19:25.114 SomeApp[2778:303] stopTracking 4310372672 1
2012-11-21 08:19:25.114 SomeApp[2778:303] dealloc 4310372672 1
Anoop Vaidya
  • 46,283
  • 15
  • 111
  • 140
Melllvar
  • 2,056
  • 4
  • 24
  • 47

1 Answers1

1

It sounds like you want to persist the properties – is that right?

You'll probably have an easier time if you adjust your design by storing the cell properties in your model objects instead of the NSCell, and having the cell or table view delegate fetch the value from the model.

What particular behavior are you trying to achieve using this property?

paulmelnikow
  • 16,895
  • 8
  • 63
  • 114
  • This cell will eventually contain other properties. At the moment, I'm trying to implement a custom cell that will intercept keyboard shortcuts (similar to [ShortcutRecorder](http://code.google.com/p/shortcutrecorder/), but inside an NSTableView. This particular property would track whether the cell is in an edit state. – Melllvar Nov 21 '12 at 19:01
  • Is the cell actually receiving keyboard events when it's not in an editing state? Also, have you considered overriding NSTextFieldCell instead of NSActionCell? Something else I've done in a similar situation is have an NSTableView subclass which keeps track of the editing row and column – overriding `-editColumn:row:withEvent:select:` and `-textDidEndEditing`. – paulmelnikow Nov 21 '12 at 21:45
  • I don't think I can use NSTextField - I need to intercept key events, and NSTextField suppresses `keyDown` (or `keyUp` - I can't recall). I might try it again, if all else fails (though I doubt I'll be able to get much farther) - it's just that the absence of documentation and examples on a similar topic is surprising. – Melllvar Nov 22 '12 at 05:16
  • While you're editing the cell or not? I'm surprised to hear that it suppresses keyboard events. Is the tableview getting those events? By the way, NSTextFieldCell is a different class than NSTextField. – paulmelnikow Dec 02 '12 at 16:52