我试图从类中获取OpenGL ES本机窗口(_win):
@interface CAEAGLLayer : CALayer <EAGLDrawable>
{
@private
struct _CAEAGLNativeWindow *_win;
}
所以我用类别扩展了它:
@interface CAEAGLLayer(MyLayer)
- (void*) fetchWin;
@end
@implementation CAEAGLLayer(MyLayer)
- (void*) fetchWin
{
return self->_win;
}
@end
并在另一个班级中使用它:
@implementation MyClass
- (void)setupLayer
{
_eaglLayer = (CAEAGLLayer*)self.layer;
_eaglLayer.opaque = YES;
NSLog(@"_eaglLayer _win: %p", [_eaglLayer fetchWin]);
}
@end
但是在构建时遇到了链接错误:
Undefined symbols for architecture x86_64:
"_OBJC_IVAR_$_CAEAGLLayer._win", referenced from:
-[CAEAGLLayer(MyLayer) fetchWin] in OpenGLView.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
答案 0 :(得分:1)
链接器找不到符号,因为默认情况下,“@private
和@package
ivars are not exported的ivar符号”。因此,即使您有一个引用它的标题,您也无法以这种方式直接通过名称访问_win
。
但是,您可以深入了解ObjC运行时并提取实例变量。在您的情况下,您可以在-setupLayer
(#importing <objc/objc-runtime.h>
之后)尝试类似的内容:
Ivar winIvar = class_getInstanceVariable([CAEAGLLayer class], "_win");
void * winptr = (__bridge void *)object_getIvar(_eaglLayer, winIvar);
(您也可以使用-valueForKey:
作为密钥的名称在图层上使用简单的@"_win"
,但我更喜欢运行时方法,因为他们会更清楚地了解您正在尝试的内容要做,这基本上绕过了预期的抽象。)