views:

172

answers:

5

What is the easiest way to create a global object. I have tried declaring the object outside the method with no luck.

@implementation UV_TouchpadViewController;
NSMutableString *string = [NSMutableString stringWithFormat:@"text"];
A: 

Do you need it for each instance of the class? If so, you should make it an Instance variable. Put

NSMutableString *string;

In your header

And then you can set it in any method in your class.

If this isn't what you meant, update your question or comment.

Tom H
+3  A: 

Very close -- you can't initialize a non-local variable with a non-const expression, and a method call is inherently non-const, even if it looks like it should be. So basically, change it to

NSMutableString *string;

but if it's only going to be used inside the implementation file (eg. other classes would only get at it through UV_TouchpadViewController, not get/set it directly (this is also the recommended pattern)), then qualify it as static, like so

static NSMutableString *string;

If on the other hand you do want to be able to access it directly from outside UV_TouchpadViewController, leave off the static, but add

extern NSMutableString *string;

to your header file (outside the class @interface), and whomever includes the header will be able to access it. (Note that you could instead just put NSMutableString *string; in your header file, however this is quickly becomes unclear)

Also, if you are trying to do this for a singleton class, (I can't think of a good reason to have a global mutable string -- you know they're not thread safe right?) I recommend reading Apple's docs on singletons first, where they suggest you use ivars, not global variables, even for singletons. However, UV_TouchpadViewController should not even be a singleton (if it is in any way a view controller), it should just have a single instance, if that's all you want.

If on the other hand you just want all UV_TouchpadViewControllers to have access to this one variable, note that across almost all languages this is considered a bad design pattern (globals are bad), and that you should instead stick it in, say, your app delegate (which is guaranteed to have a single globally accessible instance), where it can be an ivar+accessors, and generally considered a setting and (with a little extra code) persisted.

EDIT:

If you want to have a singleton that maintains global state, which I still recommend against -- you should create a class, like for instance ApplicationState, which handles all of the application's global state as a model object in the traditional model-view-controller pattern. I wont go into detail here because that would be highly redundant of a google search.

In your Application Delegate, somewhere, add an ivar ApplicationState *state, and a corresponding @property (and @synthesize in the implementation file).

Jared P
Its sounds like I need a singleton unless you could help steer me in a better direction. I am not actually trying to create a shared string through my view controller. I actually have a class that contains all of the logic of my application and I need to init one object of the class and have retained through all of the calls the veiw controller methods call. It seems logical to initialize it once globally so all off the other methods have access to its one instance. Is this something that could be accomplished in the the AppDelegate ?
jcb344
Yes, your last suggestion seems the best -- create a class to hold the application logic, the one that you only want one instance of, and then create an instance in an ivar from a place that there will only be one instance, such as the app delegate. That way you only have to [[UIApplication sharedApplication].appDelegate.applogic somecall]. This seems ugly, and is, but if you need a singleton this is at least the clearest way to go. On the other hand, application logic (games generally notwithstanding) should really go into a high level view controller, which will only be instantiated once.
Jared P
Could you give some code examples of what would go into the AppDelegate.h, AppDelegate.m, viewcontrolloer.h and viewcontrolloer.m to implement and utilize the AppDelegate global declaration and init of the object . I am a bit unsure of how to set this method up and how to declare and instance of ivar for the object. Thank you.
jcb344
A: 

You can achieve that by implementing getter and setters in the delegate class.

In delegate .h file

Include UIApplication delegate

 @interface DevAppDelegate : NSObject <UIApplicationDelegate>

  NSString * currentTitle;

 - (void) setCurrentTitle:(NSString *) currentTitle;
 - (NSString *) getCurrentTitle; 

In Delegate implementation class .m

 -(void) setCurrentLink:(NSString *) storydata{
currentLink = storydata;

}

-(NSString *) getCurrentLink{
if ( currentLink == nil ) {
    currentLink = @"Display StoryLink";
}
return currentLink;
}

So the variable you to assess is set in the currentlink string by setters method and class where you want the string ,just use the getter method.

AppDelegate *del=(AppDelegate *)[[UIApplication sharedApplication]delegate];
TO set:
[del setCurrentLink];
TO Get:
NSString *value=[del getCurrentLink];

All the best

Warrior
A: 

Add:

NSMutableString *globalString = nil;

to any .m file of any object. The nil initialization adds a little safety, since nil objects can be "safely" messaged without outright crashing the app.

Add:

extern NSMutableString *globalString;

to the headers of any other objects that needs to access this global.

Add:

if (globalString == nil) {
    globalString = [ [ NSMutableString stringWithFormat:@"text"] retain ];
}

to the init of any class(es) that could be the very first to touch this global, or to some init that happens even earlier.

Globals are a less verbose form of singleton, but with no access restriction or tracking. Use with caution.

hotpaw2
+1  A: 

There are few easier ways to shoot yourself in the foot than by using global variables.

You should never expose a dumb object like a string which has no access control to every object in the app. Any random piece of code anywhere in the app can change the mutable string leading to chaos as the app grows larger.

Usually when people want a global variable what they actually need is either the user defaults or a data model.

The user defaults (NSUserDefaults) is the preference persistence system that saves application state and user's settings both between launches and as the app runs. You can park small bits of data, such as strings, in the defaults and access them easily from anywhere in the app.

A data model is dedicated object that holds the applications data and manages access to it such that only the data model has final control. This makes it easy to tell what has changed the data and how. The data model can be a simple custom class or something elaborate such as core date. You can park the data model in the app delegate or create it as a singleton as the other answered have explained.

I have been using the Apple API for years and I have never needed to use a real global variable. If you think you need one, you probably have misunderstood something about application design in the Apple API. You might want to post a question explaining what you're trying to do with a global variable and what the best strategy should be for doing it without the dangers of using a global variable.

TechZen