简体   繁体   中英

NSCell's unexpected behavior

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

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?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM