EDIT: I'm not going to do this, I now realize how dangerous this can be. But, the question stays for purely academic purposes.
编辑:我不会这样做,我现在意识到这可能有多危险。但是,问题仍然存在于纯粹的学术目的。
I'm trying to implement a category on NSCollectionView that will let me access the private variable _displayedItems. I need to be able to access it in my subclass. So, I've created the following category:
我正在尝试在NSCollectionView上实现一个类别,它允许我访问私有变量_displayedItems。我需要能够在我的子类中访问它。所以,我创建了以下类别:
@interface NSCollectionView (displayedItems)
- (NSMutableArray *)displayedItems;
@end
@implementation NSCollectionView (displayedItems)
- (NSMutableArray *)displayedItems
{
return _displayedItems;
}
@end
...which seems like it should work perfectly. However, when I try to compile this, the linker gives me the following error:
......看起来应该完美无缺。但是,当我尝试编译它时,链接器给我以下错误:
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
I know for a fact that _displayedItems exists in NSCollectionView, I've looked at the interface and also printed it's contents using gdb. Does anyone know of a way to fix this?
我知道_displayedItems存在于NSCollectionView中,我查看了界面并使用gdb打印了它的内容。有谁知道解决这个问题的方法?
Thanks in advance!
Billy
提前致谢!比利
2 个解决方案
#1
12
_displayedItems
is a private ivar, so you shouldn't access it, even from a category.
_displayedItems是一个私有的ivar,所以你不应该访问它,即使是从一个类别。
That said, you should try compiling the same code with
也就是说,您应该尝试使用相同的代码编译
gcc -arch i386
and
gcc -arch x86_64
and see the difference. In the 32 bit mode you don't see the error. This shows how fragile the situation is. You really shouldn't.
并看到差异。在32位模式下,您没有看到错误。这表明形势是多么脆弱。你真的不应该。
That said, there's a way to get that ivar by abusing KVC:
也就是说,有一种方法可以通过滥用KVC获得这种方法:
@implementation NSCollectionView (displayedItems)
- (NSMutableArray *)myDisplayedItems
{
return [self valueForKey:@"displayedItems"];
}
@end
Note that you shouldn't name your method just as displayedItems
. That would make an infinite loop, because the KVC machinery would find your method earlier than the ivar. See here.
请注意,您不应将您的方法命名为displayedItems。这会产生一个无限循环,因为KVC机器会比ivar更早地找到你的方法。看这里。
Or you can access any hidden ivar using Objective-C runtime functions. That's also fun.
或者您可以使用Objective-C运行时函数访问任何隐藏的ivar。这也很有趣。
However, let me say again. There's a big difference in knowing you can do one thing and doing that thing for real. Just think of any hideous crime. and doing that by yourself.
但是,让我再说一遍。知道你可以做一件事并做真实的事情有很大的不同。想想任何可怕的罪行。并亲自做到这一点。
DON'T DO THAT!!!!!
#2
5
You shouldn't really, but access it like a pointer to a member of a struct:
你不应该真的,但访问它就像指向结构成员的指针:
-(NSMutableArray *)displayedItems {
return self->_displayedItems;
}
This is a fragile thing to do, as I'm sure you're aware however ;)
这是一件很脆弱的事情,因为我确信你知道;)
UPDATE: Since you've mentioned the above doesn't work, try dropping down to the runtime:
更新:由于您已经提到上面的内容不起作用,请尝试下载到运行时:
-(NSMutableArray *)displayedItems {
NSMutableArray *displayedItems;
object_getInstanceVariable(self, "_displayedItems", (void *)&displayedItems);
return displayedItems;
}
(Tested, works)
#1
12
_displayedItems
is a private ivar, so you shouldn't access it, even from a category.
_displayedItems是一个私有的ivar,所以你不应该访问它,即使是从一个类别。
That said, you should try compiling the same code with
也就是说,您应该尝试使用相同的代码编译
gcc -arch i386
and
gcc -arch x86_64
and see the difference. In the 32 bit mode you don't see the error. This shows how fragile the situation is. You really shouldn't.
并看到差异。在32位模式下,您没有看到错误。这表明形势是多么脆弱。你真的不应该。
That said, there's a way to get that ivar by abusing KVC:
也就是说,有一种方法可以通过滥用KVC获得这种方法:
@implementation NSCollectionView (displayedItems)
- (NSMutableArray *)myDisplayedItems
{
return [self valueForKey:@"displayedItems"];
}
@end
Note that you shouldn't name your method just as displayedItems
. That would make an infinite loop, because the KVC machinery would find your method earlier than the ivar. See here.
请注意,您不应将您的方法命名为displayedItems。这会产生一个无限循环,因为KVC机器会比ivar更早地找到你的方法。看这里。
Or you can access any hidden ivar using Objective-C runtime functions. That's also fun.
或者您可以使用Objective-C运行时函数访问任何隐藏的ivar。这也很有趣。
However, let me say again. There's a big difference in knowing you can do one thing and doing that thing for real. Just think of any hideous crime. and doing that by yourself.
但是,让我再说一遍。知道你可以做一件事并做真实的事情有很大的不同。想想任何可怕的罪行。并亲自做到这一点。
DON'T DO THAT!!!!!
#2
5
You shouldn't really, but access it like a pointer to a member of a struct:
你不应该真的,但访问它就像指向结构成员的指针:
-(NSMutableArray *)displayedItems {
return self->_displayedItems;
}
This is a fragile thing to do, as I'm sure you're aware however ;)
这是一件很脆弱的事情,因为我确信你知道;)
UPDATE: Since you've mentioned the above doesn't work, try dropping down to the runtime:
更新:由于您已经提到上面的内容不起作用,请尝试下载到运行时:
-(NSMutableArray *)displayedItems {
NSMutableArray *displayedItems;
object_getInstanceVariable(self, "_displayedItems", (void *)&displayedItems);
return displayedItems;
}
(Tested, works)