Неожиданное поведение NSCell

Я реализую подкласс NSActionCell (внутри NSTableView) и заметил что-то необычное. Если я устанавливаю свойство (isEditing), когда пользователь щелкает ячейку, значение этого свойства теряется, потому что вскоре после этого высвобождается NSCell. Я предположил, что это происходит из-за неправильной обработки копирования, поэтому добавил copyWithZone. Теперь я вижу, что вызывается copyWithZone, но он вызывается в неожиданном экземпляре, а свойство этого экземпляра равно NO — значение по умолчанию. Каждый раз, когда вызывается copyWithZone, он вызывается в одном и том же экземпляре.

Может ли кто-нибудь пролить свет на это поведение? Я присоединяю рассматриваемый подкласс и результат, который я получаю. Что именно мне нужно сделать, чтобы свойства ячейки сохранялись, когда пользователь нажимает на разные ячейки?

@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

Вывод (выдается, когда пользователь щелкает ячейку):

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

и еще один клик (в другой ячейке):

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

person Melllvar    schedule 21.11.2012    source источник


Ответы (1)


Похоже, вы хотите сохранить свойства — верно?

Вам, вероятно, будет легче, если вы настроите свой дизайн, сохранив свойства ячейки в объектах вашей модели, а не в NSCell, и если делегат представления ячейки или таблицы извлечет значение из модели.

Какого конкретного поведения вы пытаетесь добиться, используя это свойство?

person paulmelnikow    schedule 21.11.2012
comment
Эта ячейка в конечном итоге будет содержать другие свойства. На данный момент я пытаюсь реализовать пользовательскую ячейку, которая будет перехватывать сочетания клавиш (аналогично ShortcutRecorder, но внутри NSTableView.Это конкретное свойство будет отслеживать, находится ли ячейка в состоянии редактирования. - person Melllvar; 21.11.2012
comment
Действительно ли ячейка получает события клавиатуры, когда она не находится в состоянии редактирования? Кроме того, рассматривали ли вы переопределение NSTextFieldCell вместо NSActionCell? Что-то еще, что я сделал в похожей ситуации, — это подкласс NSTableView, который отслеживает редактируемые строки и столбцы — переопределяя -editColumn:row:withEvent:select: и -textDidEndEditing. - person paulmelnikow; 22.11.2012
comment
Я не думаю, что смогу использовать NSTextField — мне нужно перехватывать ключевые события, а NSTextField подавляет keyDown (или keyUp — не помню). Я мог бы попробовать еще раз, если ничего не помогает (хотя я сомневаюсь, что смогу продвинуться намного дальше) - просто удивительно отсутствие документации и примеров по похожей теме. - person Melllvar; 22.11.2012
comment
Пока вы редактируете ячейку или нет? Я удивлен, узнав, что он подавляет события клавиатуры. Получает ли tableview эти события? Кстати, NSTextFieldCell — это другой класс, чем NSTextField. - person paulmelnikow; 02.12.2012