【问题标题】:IBOutlet like constructs in the Objective-C runtimeObjective-C 运行时中的类似 IBOutlet 的构造
【发布时间】:2009-07-29 06:37:51
【问题描述】:
我对 IBOutlets 的理解是它们充当了 Objective-C 类中 ivars 和属性的标记。 Objective-C 运行时中是否有任何东西可以让人们在运行时查询 ivar 或属性或类是否已用 IBOutlet 标记?还是 XCode 只是在编译时对这些做了一些巧妙的处理?
如果它们是运行时构造,是否可以定义自己的标记并以这种方式使用它们:
@private
MyMarker MyClass instance;
【问题讨论】:
标签:
objective-c
objective-c-runtime
【解决方案1】:
据我了解,Interface Builder 只是读取头文件。 IBOutlet 和 IBAction 是微不足道的#defines:
#define IBOutlet
#define IBAction void
完全不影响编译。 Interface Builder直接读取你的头文件(当头文件发生变化时是notified by Xcode,但它只是读取和解析头文件本身。
当 nib 文件被取消归档时,值是通过普通接口使用 ivar 或属性设置的,但没有什么特别注意 ivar/property 可由 Interface Builder 使用。
所以不,IBOutlet/IBAction 属性的存在没有存储,无法访问,也不能添加自己的属性。
您可以查看属性,看看是否有任何有用的东西可以通过属性附加到 ivar,但我会感到非常惊讶。
【解决方案2】:
是的,IBOutlet 和 IBAction 只是在预编译阶段被解析器丢弃,所以编译后的输出中没有任何内容。如上所述,它们只是由 Interface Builder 进行文本处理,因此它知道哪些属性/方法子集可用于连接窗口。
但是,这并不能阻止您自己做同样的事情——您可以只定义一些由预处理器编译出来的#define,并使用文本处理来操作它们。但是这些在运行时都不可用,这意味着你不能真正按照你的建议去做。
在技术上可以编写一个宏来对属性/ivar 进行一些操作,然后将额外信息添加到不同的 ivar;例如:
#define OUTLET(type,name) type name;BOOL property_##name;
@interface Foo : NSObject
{
OUTLET(NSString*,foo);
}
@end
将扩展为
@interface Foo :NSObject
{
NSString* foo;
BOOL property_foo;
}
@end
然后您可以使用 property_foo 的存在来处理您的代码(在运行时和编译时应该可以检测到)。
我一般不建议尝试这样做...首先,它会使您的界面(以及因此的内存对象)比它们需要的更大。您最好创建自己的类(或结构 typedef)来保存您想要的附加信息。