Objective-C覆盖[NSObject初始化]是否安全?

时间:2011-01-12 12:38:48

标签: objective-c initialization nsobject

基本上,我有以下代码(在此解释:Objective-C Constants in Protocol

// MyProtocol.m
const NSString *MYPROTOCOL_SIZE;
const NSString *MYPROTOCOL_BOUNDS;

@implementation NSObject(initializeConstantVariables)

+(void) initialize {
     if (self == [NSObject class])
     {
         NSString **str = (NSString **)&MYPROTOCOL_SIZE;
         *str = [[MyClass someStringLoadedFromAFile] stringByAppendingString:@"size"];
         str = (NSString **)&MYPROTOCOL_BOUNDS;
         *str = [[MyClass someStringLoadedFromAFile] stringByAppendingString:@"bounds"];
     }
}

@end

我想知道:我有一个类别可以覆盖NSObject的+initialize方法吗?

3 个答案:

答案 0 :(得分:14)

简而言之,不,您无法在类的类别中安全地实现+initialize方法。如果有现有实现,您将最终替换现有实现,如果一个类的两个类别都实现+initialize,则无法保证将执行该实现。

+load具有更多可预测且定义明确的行为,但由于许多事情处于未初始化状态,因此发生任何有用的事情发生得太早。

就个人而言,我完全跳过+load+initialize并使用编译器注释来使函数在加载底层二进制文件/ dylib时执行。不过,那时你几乎无法安全地做到。

__attribute__((constructor))
static void MySuperEarlyInitialization() {...}

为了响应应用程序的启动,您最好不要进行初始化。 NSApplicationUIApplication都提供委托/通知挂钩,用于在应用启动时向应用中注入一些代码。

答案 1 :(得分:2)

为什么不在MyClass类中设置这两个变量呢?而且,为什么不使用访问器?不要使用来自无处的伪常量变量,而是在应该实际使用它的类上定义一个访问器。一个简单的+(NSString *)myProtocolSize;即使在协议中也会很棒。

此外,覆盖类别中类的方法“有效”但不可靠,应该不惜一切代价避免:如果您覆盖的方法是在类别中实现的,则运行时不保证加载顺序并且您的实施可能永远不会添加到它。

答案 2 :(得分:0)

类型NSString *const的变量将始终在代码运行之前初始化,假设我们暂时忽略了C ++的变幻莫测:

NSString *const MY_PROTOCOL_SIZE = @"...";

const NSString *类型的变量(适用于const的内容的NSString关键字,而不是其地址)可以通过任何代码进行修改,但不能将消息发送给它。它违背了制作const的目的。请考虑使用全局函数:

static NSString *GetMyProtocolSize(void) {
    return [[MyClass someStringLoadedFromAFile] ...];
}

或者使用类方法:

@implementation MyClass
+ (NSString *)myProtocolSize {
    return [[MyClass someStringLoadedFromAFile] ...];
}
@end

之前您问过一个问题,为什么您的const字符串不接受动态值 - 这是因为您似乎不了解const对符号的作用。您应该阅读C中const关键字的含义,如果const不正确,应该查看另一种获取字符串的方法。