+初始化/ +加载总是以:if(self == [MyClass class])后卫开始吗?

时间:2008-11-27 21:18:57

标签: iphone objective-c cocoa macos

在你的一个Objective-C课程中实现+ initialize或+ load方法时,你总是从这种警卫开始吗?:

@implementation MyClass

+ (void)initialize {
    if (self == [MyClass class]) {
        ...
    }
}

...
@end

看起来像+ load和+ initialize中的代码通常只想执行一次。所以这有助于避免在子类加载/初始化时重复执行。

我想我只是想从一些ObjC巫师那里得到一些强化,这是必要的/普遍的做法......

这是什么常见的智慧?你会建议总是这样做吗?

对于+ load和+ initialize,你的建议是否相同,或者它们的处理方式是否存在差异?

感谢。

3 个答案:

答案 0 :(得分:5)

快速回答是:否。

可以在Apple开发人员邮件列表中找到in-depth discussion of this matter

它的要点是:

  1. 在子类上调用之前,运行时实际上会在超级类上调用+initialize
  2. 如果您包含警卫,您的类的子类具有自己的+initialize方法将不会触发相关的KVO通知。

有关第2点的示例,请务必阅读上述主题中的this post

答案 1 :(得分:4)

是的,如果要初始化只应初始化一次的全局变量,则应在初始化和加载方法中执行此操作。

那就是说,有很多情况下你可以避免它......

如果需要对每个类的每个继承者执行工作,则不应使用此条件包装:

  • 例如,将每个类的所有继承类名添加到集合中。
  • 已编辑的补充:或您正在建立KVO依赖关系(如eJames所述)

还有一些情况你不必费心:

  • 如果您执行的操作是幂等的(如果重复则不要更改值)
  • 该课程是“密封的”(没有设计的后代)

“幂等”部分是相关的。初始化器应该只是设置初始状态(每次都应该相同)。在一个好的初始化器中,重复应该无关紧要。虽然我认为如果你忘记在 重要的情况下将方法包装在条件中,这可能会很烦人。

已编辑的补充:一种不同的方法,可以正确反映任何初始化一次性要求,即测试您的初始化属性是否已初始化。即。

id myGlobalObject = nil;

+(void)initialize
{
    if (myGlobalObject == nil)
    {
        myGlobalObject = [[MyGlobalClass alloc] init];
    }
}

答案 2 :(得分:1)

YES !!!!

因为可以多次调用类的initialize方法。例如当你在父类中实现初始化,并且没有在子类中实现时,那么先调用子类,父类的初始化将被调用两次。

@implementation BaseClass

+ (void)initialize
{
    NSLog(@"BaseClass initialize self=%@, class=%@", self, [BaseClass class]);
}

@end

@interface SubClass : BaseClass
@end

@implementation SubClass

// don't implement the initialize method

@end

==================

现在首先调用SubClass,就像

一样
[SNSBaseSubLogic alloc]

查看调试控制台,输出:

BaseClass initialize self=BaseClass, class=BaseClass
BaseClass initialize self=SubClass, class=BaseClass

所以,你必须使用

+ (void)initialize
{
   if (self == [BaseClass class]) {
      NSLog(@"BaseClass initialize self=%@, class=%@", self, [BaseClass class]);
   }
}

确保方法体执行一次。