Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

RobRiley

macrumors member
Original poster
Feb 4, 2009
35
0
London
Hi,

This is probably a bit of a noob question but here goes.

My app has some constant/global variables that are set from the off and some that require setting during an authentication process such as a token. I'm having trouble with the getting/setting of external variables and it's possible I'm going about this completely the wrong way. I've re-created my code in a really simple example app to demonstrate:

constants.h

Code:
#import <Foundation/Foundation.h>

extern NSString *myConstString;
extern NSString *const anotherConstString;

@interface constants : NSObject {

}

+(void)setString:(NSString*)withString;

+(NSString*)getString;

@end

constants.m

Code:
#import "constants.h"

@implementation constants

NSString *const anotherConstString = @"12345678";

+(void)setString:(NSString*)withString{
	NSString *myConstString = [[NSString alloc] initWithString:withString];
}

+(NSString*)getString{
	NSString *myConstString2 = [[NSString alloc] init];
	return myConstString2;
}

@end

View Controller Implementation:

Code:
#import "stringTestViewController.h"
#import "constants.h"

@implementation stringTestViewController

-(IBAction)stringTest{
	[constants setString:@"1234"];
	NSString *returnedString = [constants getString];
	NSLog(@"The string is %@", returnedString);
}

So I *think* the string should be outputted to NSLog and also available to any other methods in the app, but it isn't. I'm pretty sure my initialisation of the string in the getter is wrong, but I'm not sure what to do about it.

Help anyone?

Many thanks,
 
I'd recommend using a more OO solution than externed variables. My personal choice would be to make a singleton object that holds these values. Another option is to add them to an existing singleton, say your application delegate object.
 
I'd recommend using a more OO solution than externed variables. My personal choice would be to make a singleton object that holds these values. Another option is to add them to an existing singleton, say your application delegate object.

Thanks. I read a bit about that. Back to the drawing board then. Out of interest, can you see why my code isn't working?

Thanks,
 
I don't use extern variables but I'd say that you are shadowing the declarations of the extern variables with local variables inside the methods. Where you have NSString *myConstString = you are creating a variable with local scope within that method call only.
 
Global variable are fine to use, but also very dangerous if you don't know what you're doing.

Your:

Code:
NSString *const anotherConstString = @"12345678";

attempts to do a static object alloc outside of any method. Objective C doesn't support this. You have to do this assignment inside some init method.

It should be:

Code:
NSString *anotherConstString = nil;

and in some init method

Code:
- (...) {
...
 anotherConstString = @"12345678";
...
}

If you assign another object to this global, you had better be an expert in retain/release memory management.

ADDED: you can actually code class getters and setters for global variables to more cleanly manage object memory.
 
Last edited:
@firewood, not correct. Constant external NSStrings like that work fine. You can do the same thing in C with a const char *.

What's illegal is calling a function to initialize an external variable like that. That results in an initializer is not constant error.

Code:
NSString *const anotherConstString = @"12345678"; //legal
const char * s = "whatever"; // legal
const char * s1 = somefunction(); // illegal
 
Hi,

Code:
#import "constants.h"
+(void)setString:(NSString*)withString{
	NSString *myConstString = [[NSString alloc] initWithString:withString];
}
@end


This is your problem. You're creating a local variable that hides your global string myConstString. If you really wanted to do it you should simply have this.

Code:
[myConstString release];
myConstString = [[NSString alloc] initWithString:withString];

But I think global variables like this should definitely be constant and unchanged like you did with anotherConstString. You see the problem yes? Your variable name implies that it will be constant, but then you change it! 10 to 1 if you go back to this code in a few months, you will be scratching your head as to why a variable called myConstString would change.

I typically use this method for defining preferences keys to avoid typos as I set and read them.

PrefrencesConstants.h
Code:
extern NSString const *PreferencesConstantSomeBoolConstant;
extern NSString const *PreferencesConstantSomeOtherConstant;

PreferencesConstants.m
Code:
NSString const *PreferencesConstantSomeBoolConstant = @"PreferencesConstantSomeBoolConstant";
NSString const *PreferencesConstantSomeOtherConstant = @"PreferencesConstantSomeOtherConstant";

So I can then do something like
Code:
#include "PreferencesConstants.h"

[[NSUserDefaults standardDefaults] boolForKey:PreferencesConstantSomeBoolConstant];

The key here is that these variables are never changed. As soon as you start changing global variables like this it will become hard to determine what is going on where, and it will be very easy to mess up. Do yourself a favor and if the data has any chance at all of changing, put it in a class as a member variable (hopefully a class that makes sense to own the data).
 
Thanks everyone. Yes that makes a little more sense now..

So basically I have a method in my view controller that needs to set a variable during an authentication process that remains for the lifecycle of the app and is available to all other methods in all classes. What is the recommended way to do this? Can anyone give me a simple code example?

Thanks again.
 
Thanks everyone. Yes that makes a little more sense now..

So basically I have a method in my view controller that needs to set a variable during an authentication process that remains for the lifecycle of the app and is available to all other methods in all classes. What is the recommended way to do this? Can anyone give me a simple code example?

Thanks again.

I would store it as a member of the AppDelegate, that's always easy to get to...

Code:
[(MyAppDelegate*)[[UIApplication sharedApplication] delegate] setVariable:variable];
SomeClass *class = [(MyAppDelegate*)[[UIApplication sharedApplication] delegate] variable];

If you want it to be persistent across app launches you can look at NSUserDefaults, or the Keychain if it is sensitive data.
 
I would store it as a member of the AppDelegate, that's always easy to get to...

Code:
[(MyAppDelegate*)[[UIApplication sharedApplication] delegate] setVariable:variable];
SomeClass *class = [(MyAppDelegate*)[[UIApplication sharedApplication] delegate] variable];

If you want it to be persistent across app launches you can look at NSUserDefaults, or the Keychain if it is sensitive data.

Thanks - that looks very useful :)
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.