tags:

views:

263

answers:

2

I am trying to save my data from a view that was loaded on applicationWillTerminate but am running into a few problems.

I have four views: inFinateViewController FirestViewController SecondViewController ThirdViewController

I am loading my views from like this (thanks to Mauricio Giraldo code) via the infinateViewController:

- (void) displayView:(int)intNewView {

NSLog(@"%i", intNewView);   

[self.currentView.view removeFromSuperview];
[self.currentView release];
switch (intNewView) {
    case 1:
        self.currentView = [[FirstViewController alloc] initWithNibName:@"FirstView" bundle:nil];
        break;
    case 2:
        self.currentView = [[SecondViewController alloc] initWithNibName:@"SecondView" bundle:nil];
        break;
    case 3:
        self.currentView = [[ThirdViewController alloc] initWithNibName:@"ThirdView" bundle:nil];
        break;
}

[self.view addSubview:self.currentView.view];

CATransition *animation = [CATransition animation];
[animation setDelegate:self];
[animation setType:kCATransitionReveal]; 
[animation setDuration:0.75];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]]; 
[[self.currentView.view layer] addAnimation:animation forKey:kCATransition];

}

And it starts up via:

- (void)viewDidLoad {
self.currentView = [[FirstViewController alloc]
               initWithNibName:@"FirstView" bundle:nil];
[self.view addSubview:self.currentView.view];
[super viewDidLoad];
}

In my SecondViewController, I have a NSMutableArray that on start, I initialize with numbers, scramble them, and then use. My goal is to save these entries when the applicationWillTerminate is called.

In my SecondViewController I also have a method that has:

-(void) saveExitData
{
[pnames writeToFile:[self saveFilePath: @"gameArrayData.plist"] atomically:YES];

 }

My problem is that the applicationWillTerminate is in the appDelegate and although I am calling it, it does not seem to run. I attempted to step into it via debugger, but it only hits it and never jumps into it. Code is:

- (void)applicationWillTerminate:(UIApplication *)application {
[secondViewController saveExitData];

} 

My infinateViewsAppDelegate looks like this:

//  InfiniteViewsAppDelegate.h
#import <UIKit/UIKit.h>
@class SecondViewController;
@class InfiniteViewsViewController;

@interface InfiniteViewsAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
InfiniteViewsViewController *viewController;
SecondViewController  *secondViewController;

}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet InfiniteViewsViewController *viewController;
@property (nonatomic, retain) IBOutlet SecondViewController *secondViewController;

-(void) displayView:(int)intNewView;

@end

and the .m File:

//  InfiniteViewsAppDelegate.m
#import "SecondViewController.h"
#import "InfiniteViewsAppDelegate.h"
#import "InfiniteViewsViewController.h"

@implementation InfiniteViewsAppDelegate

@synthesize window;
@synthesize viewController;
@synthesize secondViewController;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

[window addSubview:viewController.view];

[window makeKeyAndVisible];

return YES;
 }

- (void)displayView:(int)intNewView {
[viewController displayView:intNewView];
}

- (void)dealloc {
[viewController release];
[window release];
[super dealloc];
}


@end

So, I guess my question is, how would I be able to save this data? Can the applicationWillTerminate be placed in my SecondViewController so I could write the data and save from there? Or does applicationWillTerminate only exist in the appDelegate?

Thanks to anyone who can shed some light on this. I have read books upon books and googled forever...but still no answer.

Geo...

+1  A: 

If your app delegate is set up correctly, applicationWillTerminate: should definitely be called. You should investigate this because if it isn't, you have an error somewhere.

It's not necessary to solve your problem, though: besides applicationWillTerminate:, the UIApplication instance will also send out a notification named UIApplicationWillTerminateNotification on exit. You can have your view controllers observe this notification and then there is no need for your app delegate to maintain a reference to your view controllers.

When a view controller is created, have it register for the notification:

[[NSNotificationCenter defaultCenter] addObserver:self 
                                         selector:@selector(applicationWillTerminateNotification:)
                                             name:UIApplicationWillTerminateNotification
                                           object:[UIApplication sharedApplication]];

The notification center will then call the selector you specified and you can save your stuff in that method:

- (void)applicationWillTerminateNotification:(NSNotification *)notification {
    // save stuff ...
}

Don't forget to unregister yourself when the view controller is deallocated:

[[NSNotificationCenter defaultCenter] removeObserver:self 
                                                name:UIApplicationWillTerminateNotification 
                                              object:[UIApplication sharedApplication]];
Ole Begemann
This is exactly what I needed...thanks so much! Also, as an FYI, what I meant was the applicationWillTerminate was firing, just wasn't calling what I thought it would. Anyway, so one last question on this: Does this mean the appliationWillTerminate in the appDelegate is still the "default" for the other views unless I were to register their own notification?
George
`applicationWillTerminate:` will always be called, regardless of whether you listen to the notification or not. I don't know what you mean by "default", though. If your app delegate already has a reference to a view controller, you might as well use it in applicationWillTerminate:, but if not, I think the notification is the better way.Even better, wherever possible save your state continuously whenever it changes, not just on application exit.
Ole Begemann
Wouldn't that be more over head saving state after each change? Also, what I meant by default was that if I did not create a notification, would it use the applciationWillTerminate from the appDelagate. But, from what I gather you are saying is, the applicationWillTerminate from the appDelegate is called always? Even though I created this new notification? Which would mean it is hitting my applicationWillTerminateNotification and the applicationWillTerminate, right? Thx again.
George
Overhead depends on how often your state changes and how much data there is to write. You should definitely save state periodically and not just on app exit. Otherwise, if your app crashed, the user might lose a lot of data.
Ole Begemann
A: 

I don't see applicationWillTerminate in your code--it should be in InfiniteViewsAppDelegate.m. That's where it will be seen and called.

Ole Bergemann is right about notifications, and that's a great solution. If you don't want to use them though, it's also easy to have your app delegate tell each of the views to clean themselves up (since it happens to already have properties for each of them). Just make sure your InfiniteViewsAppDelegate is actually set as the app's delegate, and make sure applicationWillTerminate is right in InfiniteViewsAppDelegate.m.

andyvn22