在objective-c中定义一个常量

Ily*_*ski 16 constants objective-c

我想在objective-c中定义一个常量.

以前我有以下功能:

+(NSString *) getDocumentsDir {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
    NSString *documentsDir = [paths objectAtIndex: 0];
    paths = nil;
    return documentsDir;
}
Run Code Online (Sandbox Code Playgroud)

我想只定义一个常量"Documents_Dir" - 当函数被调用时,之后访问以前创建的值.

我尝试了以下代码,但没有用:

#define getDocumentsDir \
{   \
#ifdef Documents_Dir    \
return Documents_Dir;   \
#else   \
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);  \
NSString *documentsDir = [paths objectAtIndex: 0];  \
#define Documents_Dir [paths objectAtIndex: 0]; \
paths = nil;    \
return Documents_Dir;   \
#endif  \
}   \
Run Code Online (Sandbox Code Playgroud)

我对预编译器指令不太满意,所以任何帮助都将不胜感激.

Qui*_*lor 34

序言:理解预编译器指令和真实常量之间的区别是值得的.一个#define只是做一个文本替换编译器生成的代码之前.这对于数值常量和typedef很有用,但对于函数或方法调用并不总是最好的想法.我假设您确实需要一个真正的常量,这意味着创建搜索路径的代码应该只执行一次.


MyClass.m文件中,定义变量并将其填充到如下+initialize方法中:

static NSArray *documentsDir;

@implementation MyClass

+ (void) initialize {
    if (documentsDir == nil) {
        documentsDir = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES) lastObject] retain];
    }
}

...

@end
Run Code Online (Sandbox Code Playgroud)

static修饰使得它只有在它被声明的编译单元可见.对于一个简单的常数,这就是你所需要的.

如果该类具有子类,+initialize则将为每个子类调用一次(默认情况下),因此您需要在分配之前检查是否documentsDir存在nil,因此不会泄漏内存.(或者,正如Peter Lewis指出的那样,您可以使用其中一个==-isMemberOfClass:方法检查当前正在初始化的类是否为MyClass .)如果子类还需要直接访问常量,则需要预先声明变量如externMyClass.h文件(其子类包括):

extern NSArray *documentsDir;

@interface MyClass : NSObject
...
@end
Run Code Online (Sandbox Code Playgroud)

如果将变量预先声明为extern,则必须从定义中删除static关键字以避免编译错误.这是必要的,因此变量可以跨越多个编译单元.(啊,C的乐趣...)

注:在Objective-C代码,更好的方式来声明作为东西extern是用OBJC_EXPORT(一#define宣布<objc/objc-api.h>,其基于集合的您是否正在使用C++).只需更换extern,OBJC_EXPORT你就完成了.


编辑:我刚刚发生了一个相关的问题.


Pet*_*wis 12

最简单的解决方案是将路径更改为静态变量并仅将其评估一次,如下所示:

+(NSString *) getDocumentsDir {
    static NSString *documentsDir = nil;
    if ( !documentsDir ) {
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
        documentsDir = [paths objectAtIndex: 0];
    }
    return documentsDir;
}
Run Code Online (Sandbox Code Playgroud)

"static"告诉编译器documentsDir实际上是一个全局变量,尽管只能在函数内访问.因此它被初始化为nil,并且第一次调用getDocumentsDir将重新评估它,然后进一步调用将返回预先评估的值.