Доступ к закрытой переменной в категории приводит к ошибке компоновщика - PullRequest
10 голосов
/ 13 декабря 2010

РЕДАКТИРОВАТЬ: Я не собираюсь этого делать, теперь я понимаю, насколько это может быть опасно.Но вопрос остается чисто академическим.

Я пытаюсь реализовать категорию в NSCollectionView, которая позволит мне получить доступ к закрытой переменной _displayedItems.Мне нужно иметь доступ к нему в моем подклассе.Итак, я создал следующую категорию:

@interface NSCollectionView (displayedItems)

- (NSMutableArray *)displayedItems;

@end


@implementation NSCollectionView (displayedItems)

- (NSMutableArray *)displayedItems
{
    return _displayedItems;
}

@end

... которая, кажется, должна работать идеально.Однако, когда я пытаюсь скомпилировать это, компоновщик выдает мне следующую ошибку:

Undefined symbols:
  "_OBJC_IVAR_$_NSCollectionView._displayedItems", referenced from:
      -[NSCollectionView(displayedItems) displayedItems] in NSCollectionView+displayedItems.o
ld: symbol(s) not found
collect2: ld returned 1 exit status

Я точно знаю, что в NSCollectionView существует _displayedItems, я посмотрел на интерфейс и также напечатал его содержимое, используяGDB.Кто-нибудь знает способ исправить это?

Заранее спасибо!
Билли

Ответы [ 2 ]

12 голосов
/ 13 декабря 2010

_displayedItems - это личный ивар, поэтому вы не должны получать к нему доступ даже из категории.

Тем не менее, вы должны попробовать скомпилировать тот же код с

gcc -arch i386

и

gcc -arch x86_64

и увидите разницу. В 32-битном режиме вы не видите ошибку. Это показывает, насколько хрупка ситуация. Вы действительно не должны.

Тем не менее, есть способ получить этот ивар, используя KVC:

@implementation NSCollectionView (displayedItems)

- (NSMutableArray *)myDisplayedItems
{
    return [self valueForKey:@"displayedItems"];
}

@end

Обратите внимание, что вы не должны называть свой метод так же, как displayedItems. Это сделало бы бесконечный цикл, потому что механизм KVC нашел бы ваш метод раньше, чем ivar. Смотрите здесь .

Или вы можете получить доступ к любому скрытому ивару, используя функции времени выполнения Objective C. Это тоже весело.

Однако позвольте мне сказать еще раз. Есть большая разница в том, чтобы знать, что ты можешь сделать что-то одно, и делать это реально. Просто подумай о любом отвратительном преступлении. и делать это самостоятельно.

НЕ ДЕЛАЙТЕ ЭТОГО !!!!!

5 голосов
/ 13 декабря 2010

На самом деле вы не должны этого делать, но получите к нему доступ, как указатель на член структуры:

-(NSMutableArray *)displayedItems {
  return self->_displayedItems;
}

Это хрупкая вещь, которую, я уверен, вы знаете;)

ОБНОВЛЕНИЕ: Поскольку вы упомянули, что вышеупомянутое не работает, попробуйте перейти к среде выполнения:

-(NSMutableArray *)displayedItems {
        NSMutableArray *displayedItems;
        object_getInstanceVariable(self, "_displayedItems", (void *)&displayedItems);
        return displayedItems;
}

(протестировано, работает)

...