objective-c 在objective-c中定义一个常数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1059708/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 21:48:31  来源:igfitidea点击:

Defining a constant in objective-c

objective-cconstants

提问by Ilya Suzdalnitski

I want to define a constant in objective-c.

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

Previously I had the following function:

以前我有以下功能:

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

I'd like to define a constant "Documents_Dir" only once - when the function gets called and after that to access a previously created value.

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

I've tried the following code, which didn't work:

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

#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  \
}   \

I am not strong with precompiler directives, so any help will be appreciated.

我不擅长预编译器指令,所以任何帮助将不胜感激。

回答by Quinn Taylor

Prelude:It pays to understand the difference between precompiler directives and true constants. A #definejust does a text replacement before the compiler builds the code. This works great for numerical constants and typedefs, but is not always the best idea for function or method calls. I'm operating under the assumption that you really want a true constant, meaning that the code to create the search path should only be executed once.

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



In your MyClass.mfile, define the variable and populate it in an +initializemethod like so:

在您的MyClass.m文件中,定义变量并使用如下+initialize方法填充它:

static NSArray *documentsDir;

@implementation MyClass

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

...

@end

The staticmodifier makes it visible only within the compilation unit where it is declared. For a simple constant, this is all you need.

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

If the class has subclasses, +initializewill be called once for each subclass (by default), so you'll want to check whether documentsDiris nilbefore assigning to it, so you don't leak memory. (Or, as Peter Lewis points out, you can check if the class currently being initialized is the MyClass, using either ==or the -isMemberOfClass:method.) If the subclasses also need to access the constant directly, you'd need to pre-declare the variable as externin MyClass.hfile (which the child classes include):

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

extern NSArray *documentsDir;

@interface MyClass : NSObject
...
@end

If you pre-declare the variable as extern, you must remove the statickeywordfrom the definition to avoid compile errors. This is necessary so the variable can span multiple compilation units. (Ah, the joys of C...)

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

Note:In Objective-C code, the better way to declare something as externis to use OBJC_EXPORT(a #definedeclared in <objc/objc-api.h>) which is set based on whether or not you're using C++. Just replace externwith OBJC_EXPORTand you're done.

注意:在 Objective-C 代码中,更好的方法extern是使用OBJC_EXPORT(在 中#define声明<objc/objc-api.h>),它是根据您是否使用 C++ 来设置的。只需替换externOBJC_EXPORT就完成了。



Edit:I just happened upon a related SO question.

编辑:我刚刚遇到一个相关的 SO 问题

回答by Peter N Lewis

The easiest solution is to just change paths to be a static variable and evalutate it only once, like this:

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

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

The "static" tells the compiler that documentsDir is effectively a global variable, although only accessible within the function. So it is initialized to nil, and the first call to getDocumentsDir will evalutate it and then further calls will return the pre-evalutated value.

“静态”告诉编译器,documentsDir 实际上是一个全局变量,尽管只能在函数内访问。所以它被初始化为 nil,并且第一次调用 getDocumentsDir 将评估它,然后进一步的调用将返回预先评估的值。

回答by C?ur

Small optimization regarding Peter N Lewis code:

关于 Peter N Lewis 代码的小优化:

-(NSString *) documentsDir {
    static NSString *documentsDir = nil;
    return documentsDir ?: (documentsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]);
}