I have a project, with a file that I call 'Keys.h'
In that file, I declare strings and integers that are used across the project, some of which are integers, some of which are strings.
All of the strings work fine; however, if I use integers, I get an unused variable warning.
For a string, (lfPrefs is a dictionary of user preferences)
static NSString * kUserLFPrefs = #"lfPrefs";
This works fine, and does not produce any errors.
For an integer, (I have integers to define the current mode because it seems a bit snappier than comparing strings all the time).
static int kModeLiveFeed = 1001;
static int kModeEventFeed = 2002;
These work just fine, except that they are showing an unused entity warning.
I'd prefer to use the integers over strings, mostly because I read that comparisons are much faster, takes up less memory, etc.
My question is how can I stop the warnings while still getting access to my integer keys?
(Or, should I just use strings)
I can suggest two different methods.
If you want to keep such variables in .h file, you may prefer using define if you will not be changing the value run time like;
#define kModeLiveFeed 1001
If you will be changing the variable value run time, I suggest keeping them in a .m file instead of in a .h file and creating only one instance of the .m file by using singleton. Then, even if you continue to get a warning from the .m file, you can disable it by the steps below:
Select your project from the left navigator to open project settings view.
Then, select your target.
Go to Build Phases tab and open compile resources area.
Click to the right side of your .m file to add a compiler flag as -w
I hope it helps.
You may be misunderstanding the meaning of static in C/Objective-C (this question should help). You should use const rather than static to define constants, and you should define the value of an integer/string constant in a .m file, with a corresponding declaration in the .h file. Or better yet, use an enum if you have a related set of integer constants.
Here is Apple's documentation on constants, which includes the above information as well as naming recommendations (e.g., PRConstant is preferred over the classic Mac OS-style kConstant).
Related
I want to have macros for all constant strings in the project, which I am assigned to maintain.
The format of database fields are like #"first_name", #"last_name", etc.
What I want is like follows:
#define kFirstName #"first_name"
#define kLastName #"last_name" // And so on.
Problem: I have over 3500 unique fields with constant strings. I want each one of them to be defined as macro.
Any smarter way to do this. I am thinking of manually copy, paste & edit each one of them.
Tagging as iOS & Objective-C, as the project itself is an iPad Application.
In general, defining constants like this is the way to go on iOS, so you're on the right track.
You surely won't get around typing out each of the fields at least once.
I would recommend either of two approaches:
use multiple .h-files for the definition of all the constants. you can group the header files according to the definitions that they contain (e.g. all fields related to user data in UserDefinitions.h). that way you at least make sure that you don't have to import all the constants everywhere in your code. working with prefixes will also be helpful in this situation, so prefix all the Macros names with the .h-file that they contain, e.g. kUserFirstName so that you you know at first sight where this constant comes from
define all your constants in one (or multiple) property lists. that makes them easy to maintain. only make sure that you don't load the property file each time you use one of the constants, but rather cache the file once its loaded for the first time.
When using Core Data consider using mogenerator which creates constant values for you that you can reference for all of the attribute and relationship names.
the cleanest way is to make a pair of constants files (header and main). Create a new class (inheriting from whatever, NSObject say) call it constants. Delete the #interface and #implementation, so you have an empty header (except for #import Foundation/Foundation.h) and empty main (except for importing the header.)
then declare each in the header like this
extern NSString *const kFirstName;
and implement each (in the .m file) just like this
NSString *const kFirstName = #"Johnny";
make sure the .m file is added to your target, import the header where need be.
I have an iOS application I'm writing. I've moved away from #define to create my constant values. I have a few questions regarding the use of these style declarations: NSString *const segueToMainMenu
If I'm using these internally, I'm placing them inside the .m file. However, should I be placing these wrapped around the #implementation block or outside of it or does it matter? I'm thinking inside, because they are specific to the implementation and not global, but I'm not sure. Any details are appreciated.
If I'm creating a more global scope using the extern keyword and I'm using a Constants file pair (Constants.h/Constants.m) do I need to place those in the #interface section and then define them in the #implementation section? What is the benefit of that vs the old way of just using a Constants.h file and including it with other headers? Why do I now need two files?
Is the standard practice still to name the constants with a "k" prefix (e.g. kAnimationDuration) or should I now be doing something like MainMenuViewControllerAnimationDuration? I'm imagining yes and if so, does it matter for the constants from number 1 (i.e. not extern) how I name them? In other words, are those visible outside of my implementation?
Clarification is much appreciated.
Doesn't matter whether you place them inside the implementation block or not—only methods are part of the class implementation, so the scope of constants won't change regardless.
The k prefix is a bit dated now. The usual way is to name constants as <prefix><name>, such as "MDSomeConstant".
I know this question has been asked before, but I can't seem to find information about it in Apple's documentation; maybe some of you guys did.
A lot of Objective-C code has cross-file constants in a .h file, using #define.
Others use the approach of a .m with constants and extern them in the .h file.
I understand the difference, both pros and cons, but does Apple state which one to use in iOS development?
The trouble with using #defines over an extern, is that the compiler doesn't get to do any type checking. If you #define a string, there is nothing to stop you using it where you actually want, say, a number. If you use a static NSString instead, the compiler will emit a warning if you try to use it somewhere where it isn't expecting a string.
Apple's recommendation is extern:
Define constants for strings used for such purposes as notification names and dictionary keys. By using string constants, you are ensuring that the compiler verifies the proper value is specified (that is, it performs spell checking).
Admittedly they are inconsistent about this sometimes.
A #define defines a macro which is replaced before compilation starts where as extern *** *const merely modifies a variable so that the compiler will flag an error if you try to change it. There are some cases in that you would use a #define because you can't use a extern *** *const. In theory a extern *** *const will take up memory and requires a reference to memory but this is insignificant as it maybe optimized away from the compiler.
extern *** *consts are a lot more compiler and debug friendlier then #defines this can be the deciding point when you decide which one to use.
Some see that pre-processor directives like #define are frowned upon which would suggest you should be using extern *** *const over #define
But whilst the pre-processor is frowned open some say it is more secure then a variable as it can't be changed at runtime whereas a variable can.
Both have there advantages and disadvantages and I don't think (I can't find anything myself) that Apple recommends one over the other. My personal opinion is to use a mix of them both using a pre-processor directive #define over a extern *** *const where it would seem more beneficial, this is what I do.
If you have some global constants, for example in a Constants.h which is imported in your prefix header and you're using a #define macro for these constants it's going to rebuild your whole project if you make any changes to these constants. In that case it is better to split your constants and use extern for strings, integers and everything else that you can use extern for.
For example if you have extern NSString *const kServerURL; and you change your server address it's not going to rebuild your whole project but if you use define there, it's going to rebuild it. So the only purpose at least for me is for optimising the compile time.
In some apple documentation i've seen, they suggest using a macro to check for the current version of iOS installed which could be used across your project. It looks something like this:
NSUInteger MajorVersionInstalled();
NSUInteger MajorVersionInstalled() {
// Call objective-c methods and return NSUInteger
}
#define IS_OLDER_THAN_SIX (MajorVersionInstalled() < 6)
And the idea is that you can use the macro in conditional checks across your project. I'd like to use this idea, but i'm getting a bit confused because its using a c function and i'm not sure where to define it:
Is there a place I should use to define this for use across my project (Prefix.pch ??).
Does the function implementation go in the same place??
Is there a place I should use to define this for use across my project (Prefix.pch ??).
The PCH is not a good place. It's better to put in a separate header and #import where you need it because it is likely that this declaration need not be visible everywhere. Note: The implication by using NSUInteger is also that the function is only usable in objc sources.
Does the function implementation go in the same place??
Unless you have a very specific need, the declaration:
NSUInteger MajorVersionInstalled();
belongs in a header file and the definition:
NSUInteger MajorVersionInstalled() {
// Call objective-c methods and return NSUInteger
}
belongs in an *.m file.
Once you do that, you could also create a function to get rid of #define IS_OLDER_THAN_SIX (MajorVersionInstalled() < 6).
Using the pch, definitions in the header, and foundation everywhere will often slow down your builds and can create larger binaries. It's difficult to detect this in small projects, but quickly becomes an issue in larger bodies of code and libraries.
In my first ViewController ViewControllerTest1 I've got a global variable called counter.
counter is supposed to be increased every now and then in my app. Everything works fine:
#implementation ViewControllerTest1{
int counter = 0;
-(void)viewDidLoad
{...}
-(void)method {...}
}
Now if I declare another global variable called counter in my second ViewController ViewControllerTest2 XCode gives me an error.
I know I can just give it a different name, but why does that happen? Can I make sure only the globals of the certain ViewController that is active are in my memory?
Or am I doing something like a no go right now with globals like counter?
Is there something better?
If you want a symbol to be specific to a file, use the static keyword when declaring it.
Your declaration should look like
static int counter = 0;
At link time (after all the files were compiled), the global symbols are mixed up in the same file, and therefore, if two share the same name, an error is fired by the linker.
If you define a variable at file scope (which includes locations within a class definition but outside the ivar area or a method body), it will have extern linkage by default, which requires unique symbol names.
Make it a static variable (static int ...) and the problem will be resolved, because static symbol names only need to be unique within the file in which they are declared.
If you are accessing this variable outside this file intentionally, and so need to maintain extern linkage, you will need to name the other variable something else to distinguish the two.