Global Variable? (NSString)

Discussion in 'iOS Development' started by jrcdude, Jan 8, 2010.

  1. jrcdude

    jrcdude New Member

    Joined:
    Jul 12, 2008
    Messages:
    47
    Likes Received:
    0
    Device:
    iPad 2 (White)
    Hey guys, I need an NSString to be a global variable but I can't seem to get it to work right. I tried the method of using the get() and set() functions to make it /global/ but then I got a: "'RootViewController' may not respond to '+getTheVariable'", and then when the function is called, the application terminates.

    Any help guys? I just need a simple NSString to be accessed by 2 .m files.
  2. NolesFans

    NolesFans New Member

    Joined:
    Sep 23, 2008
    Messages:
    404
    Likes Received:
    0
    Device:
    iPod touch
    I wonder which text data you uses?
  3. lauNchD

    lauNchD Well-Known Member

    Joined:
    Jan 27, 2008
    Messages:
    1,844
    Likes Received:
    261
    Device:
    iPhone 5 (Black)
    LDGlobalDictionary

    This may be a little bloated for what you want to do, but I made a globally accessable NSMutableDictionary as a coding excercise some time ago. It's not thread-safe, KVO-compliant or anything (I could make a thread-safe version if you wanted to), but it should definitely suffice!

    LDGlobalDictionary.h:
    [OBJC]#import <Foundation/Foundation.h>


    @interface LDGlobalDictionary : NSMutableDictionary
    {
    NSMutableDictionary *embeddedDict;
    }

    + (id) sharedInstance;

    @end[/OBJC]

    LDGlobalDictionary.m:
    [OBJC]#import "LDGlobalDictionary.h"

    @implementation LDGlobalDictionary

    static LDGlobalDictionary *sharedInstance = nil;

    #pragma mark Singleton stuff

    + (id) sharedInstance
    {
    @synchronized(self)
    {
    if (!sharedInstance) sharedInstance = [[self alloc] init];
    }

    return sharedInstance;
    }

    + (id) allocWithZone

    Please Register or Log in to view images

    NSZone*)zone
    {
    @synchronized(self)
    {
    if (sharedInstance)
    {
    [NSException raise: @"LDGlobalDictionarySingletonViolationException" /* I know that name is fugly

    Please Register or Log in to view images

    */ format: @"%s: Attempt to allocate a second instance!", __FUNCTION__];
    return nil;
    }

    sharedInstance = [super allocWithZone: zone];
    }

    return sharedInstance;
    }

    - (id) copyWithZone

    Please Register or Log in to view images

    NSZone*)zone
    {
    return self;
    }

    - (id) retain
    {
    return self;
    }

    - (oneway void) release
    {
    // Do nothing
    }

    - (id) autorelease
    {
    return self;
    }

    - (NSUInteger) retainCount
    {
    return NSUIntegerMax;
    }

    #pragma mark General methods

    - (id) init
    {
    if (self = [super init])
    {
    embeddedDict = [[NSMutableDictionary allocWithZone: [self zone]] init];
    }

    return self;
    }

    - (void) dealloc
    {
    sharedInstance = nil;

    [embeddedDict release];
    [super dealloc];
    }

    #pragma mark Redirection of Dictionary Methods

    /* Some of these methods aren't actually 'primitive'/necessary, but immediately redirecting the calls to the actual dictionary may be faster than letting NS[Mutable]Dictionary's default method do the work */

    - (NSUInteger) count
    {
    return [embeddedDict count];
    }

    - (id) objectForKey

    Please Register or Log in to view images

    id)aKey
    {
    return [embeddedDict objectForKey: aKey];
    }

    - (NSEnumerator*) keyEnumerator
    {
    return [embeddedDict keyEnumerator];
    }

    - (NSUInteger) countByEnumeratingWithState

    Please Register or Log in to view images

    NSFastEnumerationState *)state objects

    Please Register or Log in to view images

    id *)stackbuf count

    Please Register or Log in to view images

    NSUInteger)len
    {
    return [embeddedDict countByEnumeratingWithState: state objects: stackbuf count: len];
    }

    - (void) setObject

    Please Register or Log in to view images

    id)anObject forKey

    Please Register or Log in to view images

    id)aKey
    {
    [embeddedDict setObject: anObject forKey: aKey];
    }

    - (void) removeObjectForKey

    Please Register or Log in to view images

    id)aKey
    {
    [embeddedDict removeObjectForKey: aKey];
    }

    - (void) removeAllObjects
    {
    [embeddedDict removeAllObjects];
    }

    - (NSArray*) allKeys
    {
    return [embeddedDict allKeys];
    }

    - (NSArray*) allValues
    {
    return [embeddedDict allValues];
    }

    @end[/OBJC]

    Once you import that code into your project, you can use it like this:
    [OBJC]#import "LDGlobalDictionary.h"

    /* RootViewController */

    - (void) setNewString

    Please Register or Log in to view images

    NSString*)newString
    {
    NSMutableDictionary *dict = [LDGlobalDictionary sharedInstance];
    // You can use this like a normal mutable dictionary now
    [dict setObject: newString forKey: @"MyAwesomeKey"];
    }

    /* SomethingElseController */

    NSString *myString = [[LDGlobalDictionary sharedInstance] objectForKey: @"MyAwesomeKey"];[/OBJC]
  4. NolesFans

    NolesFans New Member

    Joined:
    Sep 23, 2008
    Messages:
    404
    Likes Received:
    0
    Device:
    iPod touch
    I don't see why you needed subclass NSMutableDictionary for that.
  5. Axis

    Axis Super Moderator Staff Member

    Joined:
    Dec 2, 2007
    Messages:
    6,288
    Likes Received:
    133
    Device:
    iPhone 4S (White)
    For something as small as this, I think it's probably best to add an ivar to the application delegate and create setters/getters for it.

    You could then do something like this:

    [[UIApplication sharedApplication].delegate myString];

    to access the string. No importing of headers necessary.

    EDIT: You may have to cast the return value of -[delegate] to a pointer to /your/ custom app delegate (especially if you want to use dot syntax). Not an issue.
  6. lauNchD

    lauNchD Well-Known Member

    Joined:
    Jan 27, 2008
    Messages:
    1,844
    Likes Received:
    261
    Device:
    iPhone 5 (Black)
    I agree. That would be the simplest solution (but the importing of headers / KVC is still necessary, because the compiler will throw a warning (NSObject<UIApplicationDelegate> might not respond to -myString) or even an error message if you use the dot syntax)

    If I'm making a global key-value collection, why not base it on something that already exists and is widely accepted/used everywhere? Subclassing NSMutableDictionary means I can automatically call all of the 'fancy' methods and categories too!
    In case you meant to ask why I didn't make an NSObject subclass and then create an accessor method for the actual dictionary: IMO, that's just pointless.
  7. jrcdude

    jrcdude New Member

    Joined:
    Jul 12, 2008
    Messages:
    47
    Likes Received:
    0
    Device:
    iPad 2 (White)
    Thanks for the help, but the first method seems monstrously large. Can you please elaborate on how to use ivar's, I can't seem to find any info on it on the web :S Also, is there not a way to access the variable from another class rather then making a global variable?

    And my final question, I can never seem to be able to call functions from other classes? How would I call this function for example from another class:

    RootViewController.h
    [OBJC]
    @interface RootViewController : UITableViewController {
    }
    - (void)doSomething;
    [/OBJC]

    RootViewController.m
    [OBJC]
    - (void)doSomething {
    //do something
    }

    - (void) otherFunction {
    [self doSomething]; //works fine
    }
    [/OBJC]

    SecondViewController.m
    [OBJC]
    - (void) anotherFunction {
    //What do I put in here to call the function correctly?
    }
    [/OBJC]

    Thanks!
  8. Axis

    Axis Super Moderator Staff Member

    Joined:
    Dec 2, 2007
    Messages:
    6,288
    Likes Received:
    133
    Device:
    iPhone 4S (White)
    If you ever "need" to call the method of one viewcontroller from another, you're doing it wrong. Explore options such as delegation.

    To add an instance variable to a class, declare it in its interface.

    eg

    [OBJC]
    @interface MyClass : NSObject {

    // ...
    NSString *myString;
    // ...

    }

    // ...

    @end

    [/OBJC]

    You'll want to write setter/getter methods for any instance variables, or let the compiler do it for you with the @property/@synthesize directives.
  9. Benito

    Benito New Member

    Joined:
    Jun 10, 2010
    Messages:
    1
    Likes Received:
    0
    Global NSObject

    Hello,

    I followed your discussion but I don't know how to solve my problem.

    I want to make an application on iPad which has many windows (4, I guess).

    In each window the user will have to cross some SegmentedControl and fill UITextFields. When he finishes, a button save will save the data and then he goes throw another window to fill other fields (1 window is sadly not enougth).

    My matter is that I want to modify the same global object at each window... which is a custom object :

    My object :
    PHP:
    @interface MyObject NSObject {
    NSMutableString *Toto;
    ...
    }
    ...
    -(
    void)addStringtoToto:(NSString *) MyString;
    ...
    -(
    void)dealloc;
    I want to build one object global to all my ViewControllers.
    I tried to define it in my AppDelegate like :
    PHP:
    MyObject *George=[MyObject alloc];
    But it returns "Initializer is not Constant"...

    Could someone help me to find a way to modify this mutable object?

    Thank you.
  10. SkylarEC

    SkylarEC Super Moderator Emeritus Staff Member

    Joined:
    Sep 19, 2007
    Messages:
    6,642
    Likes Received:
    129
    Don't use global variables. If for some reason you feel that your app absolutely needs one, then simply create a global variable like you would in any other C based language. There's no difference when using Objective-C. There is no need to severely overcomplicate things as the posters in this thread are trying to get you to do.

Share This Page