Advertise here




Advertise here

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Sign In with Google Sign In with OpenID

How to make global variables in ObjectiveC

gagandeepbgagandeepb Posts: 88Registered Users
edited December 2008 in iPhone SDK Development
I am new in ObjectiveC. I am creating one NSMutableArray object in .h file setting its property and releasing in dealloc in .m file.
Now i am adding objects in this array in the method ViewDidLoad. So the objects should remain be there in this array (like global array) until i move from this view but in my pickerView control every time when i scroll this array shows 0 object and i can't add objects every time in my picker view methods because it may slow down it when object count grows and i am fetching objects from local db.
Let me know how can we retain objects here. In .NET we use viewstate and sessions for retaining objects value when page postback or load again.
Post edited by gagandeepb on

Replies

  • rames44rames44 Posts: 365Tutorial Authors, Registered Users @ @
    edited October 2008
    One simple way to do this would be to make the array a member of your application delegate object. That object is a singleton, so it exists for the duration of your application.
    For a little fun, check out my <a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=298866985&mt=8" target="_blank">Biorhythms</a> app
  • FontanoFontano Posts: 150Registered Users
    edited October 2008
    I have/had the similar question as the OP.
    Researching last night, did lead to the similar answer from rames44.

    My new question is, is that the Preferred, Best Parctice way of doing it.
    I did a lot of google searches last night, and I couldn't identify a definitive way to do it other wise.

    I want to have a class object, that will contain a series of settings that are defined/calculated at the startup of the application. Then they will be used during the usage of the application.

    Is there a better method to make that class a singleton, similar to the UIApplication object?

    I don't mind adding it to the application delegate object, that isn't a big deal.
    I just want to know if there is a better, preferred, Best Practice way of doing it.

    <br />
    -) No matter what forum you join, you always start as a newbie. Even if you own the board.<br />
    -) There is no stupid question, if you think it is stupid don't answer it and it will fall of the screen<br />
    -) If you post some helpful sol
  • nachtnacht Posts: 88Registered Users
    edited October 2008
    Best practice is to not use global variables but to encapsulate them in preferences and/or config files. By encapsulating your variables in a Singleton for development, you can then easily make it read such a file to load the values at a later point in time and, if you are writing to them, helps you separate them out functionally.

    As to how to make a singleton, this is probably the easiest and most common pattern:
    @interface Singleton : NSObject {
    }
    
    + (Singleton *)instance;
    @end
    
    @implementation Singleton
    
    + (Singleton *)instance  {
    	static Singleton *instance;
    	
    	@synchronized(self) {
    		if(!instance) {
    			instance = [[Singleton alloc] init];
    			
    			
    		}
    	}
    	
    	return instance;
    }
    
    
    <a href="http://numbergrinder.com/" target="_blank">NumberGrinder: A Blog about numeric analysis, iphone development, business, and anything else that comes to mind</a>
  • rames44rames44 Posts: 365Tutorial Authors, Registered Users @ @
    edited October 2008
    From my point of view, the primary issue with implementing your own singleton is how any resources that the singleton holds get released or cleaned up.

    The advantage of setting things as members of the app delegate is that the lifecycle of that object is taken care of you by the system framework - you know that your app delegate will be released by the system as the application is shut down, which means you know that your "dealloc" routine will run, which means that any generalized cleanup and shutdown will definitely run. Thus, I would say that, in general, housing singleton application objects inside the app delegate is best practice. But that's just my opinion.

    Of course, there will be circumstances, such as when you're writing a framework for general use, that this won't fly. There is some documentation about creating "real" singletons in the Cocoa docs:

    Cocoa Fundamentals Guide: Creating a Singleton Instance
    For a little fun, check out my <a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=298866985&mt=8" target="_blank">Biorhythms</a> app
  • nachtnacht Posts: 88Registered Users
    edited October 2008
    Deallocation shouldn't matter if you only have to worry about it when the application shuts down: it isn't gone from the system, just from the pool allocated by that application.
    <a href="http://numbergrinder.com/" target="_blank">NumberGrinder: A Blog about numeric analysis, iphone development, business, and anything else that comes to mind</a>
  • rames44rames44 Posts: 365Tutorial Authors, Registered Users @ @
    edited October 2008
    If all you're talking about is memory, you're correct. In the more general case, however, sometimes singletons manage things other than memory that require shutdown/cleanup/whatever. That's when things get a little more twisty. This is one of those "your mileage may vary" items, because it depends what you're using the singleton for... :)
    For a little fun, check out my <a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=298866985&mt=8" target="_blank">Biorhythms</a> app
  • nachtnacht Posts: 88Registered Users
    edited October 2008
    Ah yes, I understand. I'm doing some work with that now. My solution was to have the app delegate call a shutdown method on the Singleton, since I can't do a proper shutdown hook (ala Java).
    <a href="http://numbergrinder.com/" target="_blank">NumberGrinder: A Blog about numeric analysis, iphone development, business, and anything else that comes to mind</a>
  • rames44rames44 Posts: 365Tutorial Authors, Registered Users @ @
    edited October 2008
    All a question of preferences and what syntax you want to use to access the singleton. I store mine in the app delegate, but then typically create a set of global functions like:
    MyAppDelegate* GetAppDelegate() 
    {
    	return (MyAppDelegate*)[UIApplication sharedApplication].delegate; 
    }
    
    SingletonObject* GetSingletonObject()
    {
        return [GetAppDelegate() getSingletonObject];
    }
    

    so that I can just then access things like
        [GetSingletonObject() doWhatever];
    

    as opposed to
        [[SingletonObject getSingleton] doWhatever];
    

    but it doesn't obviously really make any difference. Whatever floats your boat....
    For a little fun, check out my <a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=298866985&mt=8" target="_blank">Biorhythms</a> app
  • FontanoFontano Posts: 150Registered Users
    edited October 2008
    nacht wrote: »
    Best practice is to not use global variables but to encapsulate them in preferences and/or config files. By encapsulating your variables in a Singleton for development, you can then easily make it read such a file to load the values at a later point in time and, if you are writing to them, helps you separate them out functionally.

    As to how to make a singleton, this is probably the easiest and most common pattern:

    Yes, that will work and I will be using that for a bulk of the values.

    However, I will have two values that are received from a secure webservice upon startup, that we have an API/Defined rule, that these values can only exist in memory (aka, I should never write them to the file system; Regardless of how difficult it may be to access the file system in question)

    <br />
    -) No matter what forum you join, you always start as a newbie. Even if you own the board.<br />
    -) There is no stupid question, if you think it is stupid don't answer it and it will fall of the screen<br />
    -) If you post some helpful sol
  • FontanoFontano Posts: 150Registered Users
    edited October 2008
    rames44 wrote: »
    All a question of preferences and what syntax you want to use to access the singleton. I store mine in the app delegate, but then typically create a set of global functions like:
    MyAppDelegate* GetAppDelegate() 
    {
    	return (MyAppDelegate*)[UIApplication sharedApplication].delegate; 
    }
    
    SingletonObject* GetSingletonObject()
    {
        return [GetAppDelegate() getSingletonObject];
    }
    



    so that I can just then access things like
        [GetSingletonObject() doWhatever];
    

    as opposed to
        [[SingletonObject getSingleton] doWhatever];
    

    but it doesn't obviously really make any difference. Whatever floats your boat....


    I like that flow, mind if I use the struture?

    <br />
    -) No matter what forum you join, you always start as a newbie. Even if you own the board.<br />
    -) There is no stupid question, if you think it is stupid don't answer it and it will fall of the screen<br />
    -) If you post some helpful sol
  • nachtnacht Posts: 88Registered Users
    edited October 2008
    Fontano wrote: »
    Yes, that will work and I will be using that for a bulk of the values.

    However, I will have two values that are received from a secure webservice upon startup, that we have an API/Defined rule, that these values can only exist in memory (aka, I should never write them to the file system; Regardless of how difficult it may be to access the file system in question)

    SE best practice here would be to create a separate singleton which is responsible for grabbing and populating these variables. The grab function is then called from the init method.

    I wouldn't want to throw everything in the app delegate, especially when functions are called for, for encapsulation reasons as the app grows. YMMV.
    <a href="http://numbergrinder.com/" target="_blank">NumberGrinder: A Blog about numeric analysis, iphone development, business, and anything else that comes to mind</a>
  • PhoneyDeveloperPhoneyDeveloper Posts: 1,431Registered Users
    edited October 2008
    In order to cleanup a singleton, or anything else, you just have to register for the UIApplicationWillTerminateNotification notification. Your specified selector will be called when the user touches the home button.
  • rames44rames44 Posts: 365Tutorial Authors, Registered Users @ @
    edited October 2008
    In order to cleanup a singleton, or anything else, you just have to register for the UIApplicationWillTerminateNotification notification. Your specified selector will be called when the user touches the home button.

    I figured there had to be some kind of "shutdown hook". The trick is knowing what to search for... :)
    For a little fun, check out my <a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=298866985&mt=8" target="_blank">Biorhythms</a> app
  • GregLBSGregLBS Posts: 17Registered Users
    edited October 2008
    Can you provide a code snippet to explain and show where in the app delegate it should be placed.

    I'm struggling with the same requirement
  • PhoneyDeveloperPhoneyDeveloper Posts: 1,431Registered Users
    edited October 2008
    In your app delegate add this
    - (void)applicationWillTerminate:(UIApplication *)application
    {
    //save state here
    }
    

    In any view controller add this
    // viewDidLoad or similar
    	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:) name:UIApplicationWillTerminateNotification object:nil];
    
    Then add the applicationWillTerminate: method to the view controller

    and also add this
    - (void)dealloc 
    {
    // normal cleanup
    
    	// Unregister for the applicationWillTerminate notification
    	[[NSNotificationCenter defaultCenter] removeObserver:self];
    	
    	[super dealloc];
    }
    
  • elpuercoelpuerco Posts: 136Tutorial Authors
    edited December 2008
    HI,

    I'm trying to access an NSArray from multiple places in my app.

    The definition etc was originally in the rootviewcontroller.h and .m files where I could access it.

    I then moved it to my app delegate .h and .m files and imported this into rootviewcontroller and other places but I get errors that the array is undeclared?

    I think I have misunderstood the details of how to make this happen...?

    ???
  • nachtnacht Posts: 88Registered Users
    edited December 2008
    elpuerco wrote: »
    HI,

    I'm trying to access an NSArray from multiple places in my app.

    The definition etc was originally in the rootviewcontroller.h and .m files where I could access it.

    I then moved it to my app delegate .h and .m files and imported this into rootviewcontroller and other places but I get errors that the array is undeclared?

    I think I have misunderstood the details of how to make this happen...?

    ???

    Just to cover the simplest case, did you add accessors to your app delegate and are you casting the delegate correctly when you pull it out?
    <a href="http://numbergrinder.com/" target="_blank">NumberGrinder: A Blog about numeric analysis, iphone development, business, and anything else that comes to mind</a>
  • elpuercoelpuerco Posts: 136Tutorial Authors
    edited December 2008
    nacht wrote: »
    Just to cover the simplest case, did you add accessors to your app delegate and are you casting the delegate correctly when you pull it out?

    I have used the @property and @synthesize key words which create the assessors but not sure about the meaning of casting the delegate?

    On a side to this I have gown down the road of having a pointer which I use to reference an image passed down the pile but this is causing its own confusion as I see in the debugger that the image at top level has a value but when I set the following in place the target remains empty?
    UIImage *img = [UIImage imageNamed: [rowData objectForKey: @"myPic"]];
    
    childOfPicDetail.PicDetailPicTapped.fullSizeImage = img;
    

    so from the above the class childOfPicDetail has a UIImageView named PicDetailPicTapped that in turn has a UIImage named fullSizeImage

    When the user taps PicDetailPicTapped the image stored in fullSizeImage should be displayed......but does not
  • nachtnacht Posts: 88Registered Users
    edited December 2008
    Basically how are you accessing the delegate?
    <a href="http://numbergrinder.com/" target="_blank">NumberGrinder: A Blog about numeric analysis, iphone development, business, and anything else that comes to mind</a>
  • elpuercoelpuerco Posts: 136Tutorial Authors
    edited December 2008
    // import this to allow access to this applications application delegate
    
    #import "MyPictureAppDelegate.h"
    

    this is in my rootviewcontroller class
  • nachtnacht Posts: 88Registered Users
    edited December 2008
    Backing up slightly. Where are you accessing the values that you are getting this error and, on that note, is it a warning or an error?
    <a href="http://numbergrinder.com/" target="_blank">NumberGrinder: A Blog about numeric analysis, iphone development, business, and anything else that comes to mind</a>
  • elpuercoelpuerco Posts: 136Tutorial Authors
    edited December 2008
    I have this is the app delegate .h and .m files
    @interface......
    ...
    
    NSArray *myArray;
    
    ...
    
    @property (retain, nonatomic) NSArray *myArray;
    
    
    @implementation......
    
    @synthesize myArray;
    
    
    

    the app delegate is imported into my rootviewcontroller .m file

    and in there I have this:
    .....
    
    self.myArray = array;
    
    .....
    

    I get a red warning saying myArray not declared first used in this....
  • elpuercoelpuerco Posts: 136Tutorial Authors
    edited December 2008
    Hi,

    I am still having problems with this and find I am creating instances variables which I am passing the values of down the line to make use of them.

    Im sure this is not the way to go and by having a global variable is the answer but cant get me head around it.

    Can anyone point me in the right direction?

    Thanks
  • elpuercoelpuerco Posts: 136Tutorial Authors
    edited December 2008
    oh buggeration!!

    So this works 100% perfect....but only in one file down?

    I have an array in the app delegate h/m files and import the h file into RootViewController.m and can reference this array...yay!

    But now I have imported the .h into another .m file in my project to reference the array here too but I get an undeclared first use in error.

    So have I totally lost the plot here?

    Any help please?
Sign In or Register to comment.