Доступ к закрытой переменной в категории приводит к ошибке компоновщика
РЕДАКТИРОВАТЬ: Я не собираюсь этого делать, теперь я понимаю, насколько это может быть опасно. Но вопрос остается в чисто академических целях.
Я пытаюсь реализовать категорию в 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 ответа
_displayedItems
это частный ivar, поэтому вы не должны получать к нему доступ, даже из категории.
Тем не менее, вы должны попробовать скомпилировать тот же код с
gcc -arch i386
а также
gcc -arch x86_64
и увидеть разницу. В 32-битном режиме вы не видите ошибку. Это показывает, насколько хрупка ситуация. Вы действительно не должны.
Тем не менее, есть способ получить этот ивар, используя KVC:
@implementation NSCollectionView (displayedItems)
- (NSMutableArray *)myDisplayedItems
{
return [self valueForKey:@"displayedItems"];
}
@end
Обратите внимание, что вы не должны называть свой метод так же, как displayedItems
, Это сделало бы бесконечный цикл, потому что механизм KVC нашел бы ваш метод раньше, чем ivar. Смотрите здесь.
Или вы можете получить доступ к любому скрытому ivar, используя функции времени выполнения Objective C. Это тоже весело.
Тем не менее, позвольте мне сказать еще раз. Есть большая разница в том, чтобы знать, что ты можешь сделать что-то одно, и делать это по-настоящему. Просто подумай о любом отвратительном преступлении. и делать это самостоятельно.
НЕ ДЕЛАЙТЕ ЭТОГО!!!!!
Вы не должны на самом деле, но получить к нему доступ, как указатель на член структуры:
-(NSMutableArray *)displayedItems {
return self->_displayedItems;
}
Это хрупкая вещь, как я уверен, вы знаете, однако;)
ОБНОВЛЕНИЕ: так как вы упомянули, что выше не работает, попробуйте перейти к среде выполнения:
-(NSMutableArray *)displayedItems {
NSMutableArray *displayedItems;
object_getInstanceVariable(self, "_displayedItems", (void *)&displayedItems);
return displayedItems;
}
(Проверено, работает)