Declaring NSString constants [duplicate] - ios

This question already has answers here:
static const Vs extern const
(7 answers)
Closed 8 years ago.
Right now I am using the following way declare constants in header file:
static NSString *const RSMaxNumberOfIndustiresKey = #"MaxNumberOfIndustries";
Is it correct? I read Constants in Objective-C question but I really don't know if I really need to declare constant in 2 different places using FOUNDATION_EXPORT.

No. You should use the following in Constants.h:
extern NSString *const RSMaxNumberOfIndustiresKey;
and this in Constants.m:
NSString *const RSMaxNumberOfIndustiresKey = #"MaxNumberOfIndustries";
(i.e. add an implementation file simply to hold the single instance of the string constants).
Using your current method means there is a copy of each string within every file that includes that header.

Related

iOS: How to get the #define from a Constant.h ObjC in a Swift File? [duplicate]

This question already has answers here:
use #define in objective C and access in swift class
(2 answers)
Closed 4 years ago.
When I write this in the constant.h file:
#define WS_PLANNING_INFORMATION "registrations/"
It works when I call it from the Swift file.
But if I write this in the constant.h file:
#define WS_PLANNING_INFORMATION "registrations/" CRYPTOKEY
It doesn't work. The swift file doesn't see the WS_PLANNING_INFORMATION anymore.
Is there an easy way to concatenate two strings in the constant.h file to be well-retrieved by the swift file?
(The validate answer to this question is very useful and more simple than in that ticket, that doesn't suit me)
Use constants instead of macros.
in constant.h
extern const char *WS_PLANNING_INFORMATION;
in constant.m
const char *WS_PLANNING_INFORMATION = "registrations/" CRYPTOKEY;
If you mean to use NSString * instead of char *
in constant.h
extern const NSString *WS_PLANNING_INFORMATION;
in constant.m
const NSString *WS_PLANNING_INFORMATION = #"registrations/" CRYPTOKEY;

Linker error when referencing static NSString const in Swift [duplicate]

I created Objective C Header file. and added some properties in it.
i declared
static NSString* const kColor005C98 = #"005C98"; in Constants.h file
I defined this file in Bridging-Header file as #import "Constants.h"
Now when i want to use this property kColor005C98 in some swift file it failed the build and i am getting
Undefined symbols for architecture armv7: "_kColor005C98", referenced from:
i don't know what else i need to do so i don't get this error? (i have used this property in other objective C file successfully and no issue in that case)
Update:
As of Swift 2/Xcode 7 and later, a static constant definition like
static NSString* const kColor005C98 = #"005C98"; // in Constants.h file
is imported to Swift and can be used without problems.
(Old answer for Swift 1.x) When the code
static NSString* const kColor005C98 = #"005C98"; // in Constants.h file
is processed by an Objective-C compiler, it is treated as two things
combined into one statement:
A variable declaration which introduces an identifier and describes its type, and
a variable definition which actually instantiates/implements this identifier.
See for example
What is the difference between a definition and a declaration?
for a good explanation of the difference between declaration and
definition.
The Swift compiler treats the statement only as a declaration.
Therefore the variable is not defined anywhere, causing the linker error.
To solve the problem, you have to move the definition to an Objective-C
file:
// Constants.m:
#import "Constants.h"
NSString * const kColor005C98 = #"005C98";
and change the declaration to an extern declaration:
// Constants.h:
extern NSString * const kColor005C98;
Alternatively, you can just remove the static modifier:
NSString * const kColor005C98 = #"005C98";
to make it work with Swift. The disadvantage is that when
this line is included by multiple Objective-C files, all of them
will define a globally visible symbol kColor005C98, causing
"duplicate symbol" linker errors.
Another alternative is to use a macro definition instead:
#define kColor005C98 #"005C98"

How is static const different from extern const?

In my iOS/Objective C projects, I often have a constants.h file with my API keys and such. Until today, I've been declaring my constants as static const like so:
static NSString * const kAPIKey = #"wembvkejrvb43789gvbiu2bvfake";
This works fine, but with the unfortunate downside that I can only create constants for primitives and NSString literals, essentially. Other objects, such as UIColor objects, cannot be stored in this constant as they cannot be initialized with a static literal syntax (my understanding, citation required).
After reading some C++ docs, I understand a few things:
The static is unnecessary, as const are implicitly static.
Calling NSString * const x is actually declaring a constant and immutable value in x. I cannot change the value, but may be able to change what x points to.
This const has internal linkage, meaning the the value is defined right away (presumable at compile time).
Are these conclusions correct?
How does an extern const differ? I assume they are externally linked (thus the extern keyword). Are they defined at run time? Can I create some sort of dynamic extern const that can be set with a value returned by a class method?
For example, I would like to create a globally-scoped constant that contains a UIColor value. I would like to construct this color value using the [UIColor colorWithRed:green:blue:alpha:] class method. This clearly doesn't work with the internally linked constants I've been using (I'm assuming because it happens at compile-time) - but is it possible using an external constant, possibly set up in the +initialize method?
Any elaboration on the details of this behavior would be immensely helpful.
The static is unnecessary, as const are implicitly static.
No, that's not true.
static when used at file scope (i.e. outside any method or function) means that the variable is visible only within that file.
extern means that the variable is defined in some other file.
const means that the variable cannot be modified.
Consider strings. Often, you'll have an implementation file (name ends in .m) that defines some constant string pointer:
NSString *const SomeString = #"some string";
You might want to use that same constant from other files. If so, you could add a declaration to the header (name ends in .h) file that explains to the compiler that the variable is defined elsewhere:
extern NSString *const SomeString;
and that would let you use SomeString in any file that imports the header file. On the other hand, you might decide that you definitely do not want the constant used outside the implementation file. In that case, you could declare it static (in the implementation file again):
static NSString *const SomeString = #"some string";
and that would prevent its use from outside the file.
Calling NSString * const x is actually declaring a constant and immutable value in x. I cannot change the value, but may be able to change what x points to.
Right, it declares the pointer x to be constant -- you can't change it. You also can't change the value that it points to if it's actually a NSString because an instance NSString isn't mutable.
This const has internal linkage, meaning the the value is defined right away (presumable at compile time).
I'll take the 5th on that -- I'm not sure exactly how the compiler deals with constant strings. I think it's safe to use that as a mental model, though; the string will in any case be defined before your code ever gets to use it.
On your specific programming question, how to create a compile-time defined color object: you can't, because, apart from the handful for which the language supplies literal syntax, objects are created at runtime.
But you can still do it elegantly at runtime, without any addition to global scope, the same way the sdk does...
#interface UIColor (RainbowAddition)
+ (UIColor *)chartruseColor;
#end
#implementation UIColor (RainbowAddition)
+ (UIColor *)chartruseColor {
// bonus: this is really chartruse... according to the internet
return [self colorWithRed:0.5 green:1.0 blue:0.0 alpha:1.0];
}
#end
http://cloford.com/resources/colours/500col.htm
Objective-C is a pure extension of C, C++ is not.
At global scope:
in C (and Objective-C) writing const is equivalent to extern const (external linkage);
in C++ writing const is equivalent to static const (internal linkage).
Both in C (and Objective-C) and C++, to create a global-scoped const you can define it, just one time, in one source file like extern const TYPE identifier = VALUE; and declare it (typically in an header file) like: extern const TYPE identifier; (read it: I defined this const elsewhere at global linkage level).

Global variables in my Constants file

Until now if I needed access to a global variable across my app i just added
#define PATH [NSString stringWithFormat:#"www.url.com"]
To my Constants.h file.
I need to fetch the PATH value from my server.
How can i assign the value I'm getting from a server to a macro \string like the above and still be able to use just the variable PATH anywhere in my app? (Without naming the class like a property use such as class.PATH
This works:
#import <Foundation/Foundation.h>
NSString* PATH;
#interface Constants : NSObject
+(void)getPathFromServer;
#end
And PATH is accessible from anywhere in my app but I'm not sure if that should be the way to go.
As I understand so far, you need to define a macro which dynamic change it's url content.
If I'm right , you may need a Vararg Macros which takes a variable.
#define PATH(...) [NSString stringWithFormat:#"%#",__VA_ARGS__]
You can use extern keyword
Example :
//Header file
extern NSString * const path;
// .m file under implementation
NSString * const Ppath = [NSString stringWithFormat:#"www.url.com"];
Have a look at these
Constants in Objective C
#define vs const in Objective-C

Foundation Export [duplicate]

This question already has an answer here:
"FOUNDATION_EXPORT" vs "extern"
(1 answer)
Closed 9 years ago.
What is the use of FOUNDATION EXPORT in Objective-c?
So I have:
KError.h
FOUNDATION_EXPORT NSString *const KAPPErrorDomain;
enum {
KPUnexpectedError = -1,
};
KError.m:
#import "KError.h"
NSString *const KAPPErrorDomain = #"com.kexample.myapp";
I assume that when you use Foundation_export in this case, it is to be able to use a variable in another file?
So that in KService.m, I cam reference KAppErrorDomain without any problem?
Yes. FOUNDATION_EXPORT is a macro that expands to extern
(or extern "C" in a C++ file), and that is the
keyword to declare a variable that is shared across source files (better: shared
across "translation units").
See How do I use extern to share variables between source files?
for many good answers why extern is necessary and how it works.

Resources