5

基本上,我有以下代码(在这里解释: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方法的类别对我来说安全吗?

4

3 回答 3

14

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

+load具有更可预测和定义明确的行为,但发生得太早而无法做任何有用的事情,因为很多事情都处于未初始化状态。

就个人而言,我跳过+load+initialize完全使用编译器注释来使函数在加载底层二进制/dylib 时执行。尽管如此,当时您可以安全地做的事情很少。

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

您最好进行初始化以响应正在启动的应用程序。 NSApplication并且UIApplication两者都提供委托/通知挂钩,用于在应用程序启动时将一些代码注入应用程序。

于 2011-01-12T17:15:30.980 回答
2

为什么不在 MyClass 类中设置这两个变量呢?而且,你为什么不使用访问器?与其拥有一个不知从何而来的假常量变量,不如在一个应该实际使用它的类上定义一个访问器。一个简单的 +(NSString *)myProtocolSize; 即使在协议中也会做得很好。

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

于 2011-01-12T13:40:06.443 回答
0

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

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

于 2011-01-12T13:17:17.940 回答