0

I have a int that resets itself every time the view re-opens/leaves. I have tried every way of declaring the int that i can think of, from public, to instance variable to global variable, but it still seems to reset!

@interface MainGameDisplay : UIViewController
extern int theDay;

@implementation MainGameDisplay

- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"%i", theDay);
}

- (IBAction)returnToHome:(id)sender {
        ViewController *new = [[ViewController alloc] initWithNibName:nil bundle:nil];
        [self presentViewController: new animated:YES completion:NULL];
        NSLog(@"%i", theDay);
}

- (IBAction)theDayAdder:(id)sender {
    theDay++;
}

Okay so theDay is a global integer variable. on View load NSLog returns an output of 0. I can then click theDayAdder as many times as I want, and when I click returnToHome, it will tell me what theDay is. When I come back to MainGameDisplay page however, theDay will be reset back to zero, even though it is a global variable?

Output:
0
N (number of times you clicked 'theDayAdder' button)
0
John Topley
  • 113,588
  • 46
  • 195
  • 237
PappaSmalls
  • 349
  • 2
  • 13

3 Answers3

1

The problem is that you alloc init'ing a new instance of MainGameDisplay every time you go back to it, so of course your global variable will be reset to 0. You need to create a property (typed strong) in ViewController, use that to go back to the same instance each time.

- (IBAction)returnToGameDisplay:(id)sender {
     if (! self.mgd) {
        self.mgd = [[MainGameDisplay alloc] initWithNibName:nil bundle:nil];
     }
     [self presentViewController: self.mgd animated:YES completion:NULL];
     NSLog(@"%i", theDay);
}

In this example mgd is the property name created in the .h file.

rdelmar
  • 103,982
  • 12
  • 207
  • 218
  • 1
    How does creating a new instance of a class automatically reset a global variable back to zero? This would only be true if the instance initialization naively reset the global to zero. But so far there is no code showing that being done. – rmaddy Nov 11 '12 at 00:59
  • The question is which view is the variable global for? Is the variable global to the whole program or to the particular view in question? If the whole program, them you ought to pass it the the subviews are assigned (or weak) values. You should be outputting values that change within the live view in viewWill appear.See my answer to your question. You should have accept my answer for this question. You were outputting the value in the wrong place. – Sunny Nov 11 '12 at 01:06
  • How would the property be, I tried this but it didn't work: @property (strong) MainGameDisplay *mgd; – PappaSmalls Nov 11 '12 at 01:07
  • Did you put in an @class MainGameDisplay; at the top of the file? – rdelmar Nov 11 '12 at 01:08
  • I imported it but i'll try that. – PappaSmalls Nov 11 '12 at 01:08
  • Thank you very much, works perfectly. Now I don't have to worry about resetting everything on the view every time it opens again. You've fixed one problem and prevented many, I cannot thank you enough! – PappaSmalls Nov 11 '12 at 01:13
  • I tried using this to solve my other problem with the better view transition that I have, but it doesn't seem to work. Could you perhaps take a look at seeing what the problem might be? http://stackoverflow.com/questions/13295626/uiview-transition-causing-crash – PappaSmalls Nov 11 '12 at 01:27
  • @SinaYamani Since I solved this problem, you should except my answer, before I look at another problem – rdelmar Nov 11 '12 at 01:52
  • ("click the unaccept this answer; you accepted this answer 46 minutes ago"), plus I up-voted you as well. Also, if the view we are transitioning to is *mgd in the .h file, wont I transition to a different view if I use *mgd in a different class? – PappaSmalls Nov 11 '12 at 01:59
  • @rmaddy, it was my understanding that external and static variables are initialized to 0 (as opposed to local variables which are not). – rdelmar Nov 11 '12 at 02:04
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/19386/discussion-between-sina-yamani-and-rdelmar) – PappaSmalls Nov 11 '12 at 02:13
  • @rdelmar They me be initialized to 0 but only once. They won't be reset each time an instance is created. – rmaddy Nov 11 '12 at 05:04
0

You should know that viewDidLoad() is called when the view is loaded--not when when the view "opens" as you say. You might have a view opened in a retained value and re-opened time and time again and have vieDidLoad() called only once. However, whenever the view becomes visible, then viewWillAppear() is the delegate that is called. So, try outputting your value in viewWillAppear()--instead of viewDidLoad() and call the view appropriately (i.e., have it stick around and not created every time you need it). This will keep the view from being destroyed between calls. The code for your view should look like the following:

@interface MainGameDisplay : UIViewController
extern int theDay;

@implementation MainGameDisplay

- (void)viewDidLoad {
    [super viewDidLoad];
}

-(void) viewWillAppear:(BOOL) animated {
    [super viewWillAppear:animated];
    NSLog(@"%i", theDay);
}

- (IBAction)returnToHome:(id)sender {
        ViewController *new = [[ViewController alloc] initWithNibName:nil bundle:nil];
        [self presentViewController: new animated:YES completion:NULL];
        NSLog(@"%i", theDay);
}

- (IBAction)theDayAdder:(id)sender {
    theDay++;
}

The parent of the view (I assume the appDelegate) should do the following

@property (nonatomic, strong) MainGameDisplay *mainGameDisplay = [[MainGameDisplay alloc] initWithNib:@"MainGameDisplay" …]

ViewDidLoad() is called once--after the view is created and loaded. However, viewWillAppear() and other functions triggered by IBAction etc. are called appropriately.

Sunny
  • 1,464
  • 14
  • 26
0

extern variables are meant to be constant. If you expect your MainGameDisplay class to be long-lived, or if theDay is otherwise only supposed to be tied to that class, why not either declare theDay as a property, or, if you only ever need to set it internally in MainGameDisplay, as an ivar.

The other alternative, if you want that value to continue to exist independently of the class instance where it's declared, is to declare it static. A static var will retain its value, even across the lifetime of different instances of the class where it's declared.

KevinH
  • 2,034
  • 1
  • 12
  • 12