ChatGPT解决这个技术问题 Extra ChatGPT

What is the best way to create constants in Objective-C

I am creating a Reddit client for learning purposes. I need to have a file with constants in it. I was thinking about importing the file in the Reddit-Prefix.pch file to make the constants available to all the files. Is it a good way of doing things? Also, I've done my research and found several methods to create constants, but I don't know which one to use:

#define macro

const

static const

extern const

enum

So which way is the preferred way? What is the convention? I know that "it depends" but my question more specifically is: What are the use cases for each of those solutions?

Also, if using extern const, do I need to import the file, or the constants will be available globally without importing the file?

One thing I could logically conclude is that enum is the best choice when defining something like custom error domains (am I actually right?). But what about the others?

stackoverflow.com/questions/11153156/… please visit this link...your solution is in this post
@BhavikKama: That's a narrower question contrasting two specific solutions.
for - static const, #define , enum , this link is usefull stackoverflow.com/questions/1674032/static-const-vs-define-in-c that provides good explanation on those 3 alternative of const
enum is only useful for integral values. #define and constants can be any data type.
const, static const, and extern const are all the same except for scope. So there are really only three choices.

P
Peter Hosey

The first question is what scope you want your constants to have, which is really two questions:

Are these constants specific to a single class, or does it make sense to have them all over the application?

If they are class-specific, are they for use by clients of the class, or only within the class?

If they are specific and internal to a single class, declare them as static const at the top of the .m file, like so:

static NSString *const MyThingNotificationKey = @"MyThingNotificationKey";

If they pertain to a single class but should be public/used by other classes, declare them as extern in the header and define them in the .m:

//.h
extern NSString *const MyThingNotificationKey;

//.m
NSString *const MyThingNotificationKey = @"MyThingNotificationKey";

If they should be global, declare them in a header and define them in a corresponding module, specifically for those constants.

You can mix and match these for different constants with different levels of how global you want them to be, and for different global constants that simply don't belong together—you can put them in separate modules, each with its own header, if you want.

Why not #define?

The old answer is “macros don't have type information”, but compilers today are pretty smart about doing all the type-checking for literals (what macros expand to) as well as variables.

The modern answer is because the debugger won't know about your macros. You can't say [myThing addObserver:self forKey:MyThingNotificationKey] in a debugger command if MyThingNotificationKey is a macro; the debugger can only know about it if it is a variable.

Why not enum?

Well, rmaddy beat me to it in the comments: enum can only define integer constants. Things like serial identifier numbers, bit-masks, four-byte codes, etc.

For those purposes, enum is great and you absolutely should use it. (Even better, use the NS_ENUM and NS_OPTIONS macros.) For other things, you must use something else; enum does not do anything but integers.

And other questions

I was thinking about importing the file in the Reddit-Prefix.pch file to make the constants available to all the files. Is it a good way of doing things?

Probably harmless, but probably excessive. Import your constants header(s) where you need them.

What are the use cases for each of those solutions?

#define: Pretty limited. I'm honestly not sure there's a good reason to use this for constants anymore.

const: Best for local constants. Also, you have to use this for one you declared in a header and are now defining.

static const: Best for file-specific (or class-specific) constants.

extern const: You must use this when exporting a constant in a header.

Also, if using extern const, do I need to import the file, or the constants will be available globally without importing the file?

You need to import the file, either in each file where you use it or in the prefix header.


Why not using static NSString *const in the .h file altogether?
@IulianOnofrei: You can, if it's in an application and not a framework. If you do static NSString *const foo = @"foo";, then your header determines what the string is, and it must be the same everywhere—if you ever change the string and different parties use different versions of the header with a different string, then the strings won't match at run time. In a framework, you want to provide access to the symbol only, and let the framework be the only source of the true value of that symbol, so everyone's getting the same string from one place. That's what extern gets you.
Additional note on #defines: they're not guaranteed to have the same address in memory (depending on how they're declared, they may allocate a new instance every time they're used), so using myObject == MyDefine won't always work as expected, but myObject == MyStaticConst will.
Does it make sense in spelling like static NSString *const instead of static NSString const* ?? Any differences ?!
@kokos8998 does it make a difference? Yes it does. static NSString const * is the same as static const NSString * and means "a (changeable) pointer to a constant NSString" - which is a bit useless here as NSString is already immutable. What you want to only static NSString * const - which is a "constant pointer to an NSString"
S
Steve Moser

FOUNDATION_EXPORT

Consider using FOUNDATION_EXPORT for a bit more compatibility than extern since it is defined in foundation and compiles to compatible formats for C, C++, and Win32.

As defined in NSObjCRuntime.h

#if defined(__cplusplus)
#define FOUNDATION_EXTERN extern "C"
#else
#define FOUNDATION_EXTERN extern
#endif

#if TARGET_OS_WIN32

    #if defined(NSBUILDINGFOUNDATION)
        #define FOUNDATION_EXPORT FOUNDATION_EXTERN __declspec(dllexport)
    #else
        #define FOUNDATION_EXPORT FOUNDATION_EXTERN __declspec(dllimport)
    #endif

    #define FOUNDATION_IMPORT FOUNDATION_EXTERN __declspec(dllimport)

#else
    #define FOUNDATION_EXPORT  FOUNDATION_EXTERN
    #define FOUNDATION_IMPORT FOUNDATION_EXTERN
#endif