是否可以在调用任何类别方法之前初始化类别中的属性?

时间:2014-02-20 05:09:54

标签: objective-c objective-c-category

是否可以初始化类别中的属性?

例如,如果我在类中有一个名为nameList的可变数组属性。是否可以为此类创建一个类别,以便在调用任何类别方法之前将对象添加到数组属性中?

3 个答案:

答案 0 :(得分:3)

如果我理解正确,而其他人正在以不同方式解释您的问题,那么您拥有的是:

  • 具有属性的类
  • 该班级的类别

并且您希望在在给定实例上调用任何类别方法之前自动调用特定方法,该方法将通过修改属性来“初始化”类别方法。

换句话说,您希望使用init方法等效于子类,但使用类别。

如果我的理解是正确的,那么答案是否定的,就没有类别初始值设定项。所以重新设计你的模型不要求它,这可能只是使用一个子类 - 因为它提供了你所追求的行为。

答案很长,你可以让所有的类别方法都进行检查,比如检查你打算改变的属性,看你是否有。如果检查属性不会确定对象是否已经“类别初始化”,那么您可以使用关联对象(查看Apple的运行时文档)或其他方法来记录该事实。 / p>

HTH

附录:更长/更复杂的解决方案......

GCC& Clang都支持函数(非方法)属性构造函数,它标记了在加载时调用的函数,该函数不带任何参数并且不返回任何内容。例如,假设您有一个类Something和一个类别More,那么在类别实现文件中,通常称为Something+More.m,您可以写:

__attribute__((constructor)) static void initializeSomethingMore(void)
{
   // do stuff
}

static阻止符号initializeSomethingMore全局可见,您既不想污染全局名称空间,也不想意外调用此函数 - 所以你要隐藏它。)

将自动调用此函数,非常类似于标准类+ (void) initialize方法。然后,您可以使用Objective-C运行时函数执行的操作是将类Something的指定初始化程序实例方法替换为您自己的实现。这些应首先调用原始实现,然后在返回对象之前初始化类别。在概述中,您可以定义一个方法:

- (id) categoryVersionOfInit
{
    self = [self categoryVersionOfInit]; // NOT a mistake, see text!
    if (self)
    {
       // init category
    }
    return self;
}

然后在initializeSomethingMore 切换 initcategoryVersionOfInit的实现 - 所以在{{1}的实例上调用init实际上调用Something。现在你在categoryVersionOfInit中看到了显然是自我递归调用的原因 - 当它被调用时,实现已被切换,因此调用调用categoryVersionOfInit的原始实现...(如果你'在这一点上重新开始画一幅画!)

使用此技术,您可以将类别初始化代码“注入”到类中。请注意,未定义调用init函数的确切位置,例如,您不能假设它将在目标类用于初始化的任何方法之前或之后调用(initializeSomethingMore,{{ 1}}或它自己的构造函数)。

答案 1 :(得分:1)

当然,可以通过objc/runtimeobjc_getAssociatedObject / objc_setAssociatedObject来实现 check this answer

答案 2 :(得分:0)

不,它在目标c中是不可能的.Category是仅向现有类添加方法的方法,您无法向其中添加属性。 阅读本文

Why can't I @synthesize accessors in a category?