Nitin Gohel
Nitin Gohel

Reputation: 49730

iOS : is it possible to open previous viewController after crashing and re-launch app?

How to achieve this stuff below? Please give me some guidance for it. I describe my issue below.

When I tap home button and remove app from tray and while I am opening app I get the login screen. I know how to use NSUserDefaults well.

But my issue is that when I navigate 3rd or 4th viewController and I press Home Button and remove app from tray, Then whenever I open app than I want to open with last open viewController.

Also same when my app is Crashing and I am opening it again then I want to open app with last open viewController state.

So I just want to know that is that possible or not? If yes, then please guide me how to achieve this stuff.

Thank you

Upvotes: 7

Views: 1586

Answers (3)

Prince Kumar Sharma
Prince Kumar Sharma

Reputation: 12641

This is not the proper answer but you can use it for Navigating view after launching.

In AppDelegate file use below codes:---

#import "NewSAppDelegate.h"
#import "NewSViewController.h"

static NewSAppDelegate *globalSelf;

@implementation NewSAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    self.viewController = [[NewSViewController alloc] initWithNibName:@"NewSViewController" bundle:nil];
    self.navController=[[UINavigationController alloc] initWithRootViewController:self.viewController];
    self.window.rootViewController = self.navController;
    [self.window makeKeyAndVisible];
    globalSelf=self;
    NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);

    return YES;
}

void uncaughtExceptionHandler(NSException *exception)
{
    UIViewController *currentVC = globalSelf.navController.visibleViewController;
    [[NSUserDefaults standardUserDefaults] setObject:NSStringFromClass(currentVC.class) forKey:@"lastVC"];
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    UIViewController *currentVC = self.navController.visibleViewController;
    [[NSUserDefaults standardUserDefaults] setObject:NSStringFromClass(currentVC.class) forKey:@"lastVC"];
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    [[NSNotificationCenter defaultCenter] postNotificationName:@"appDidBecomeActive" object:nil];
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}

In your login viewController's init method add an observer for notification and in notification method , you can apply if conditions for viewController's name received.and push to that viewController on launching LoginView controller as:---

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {

        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(openLastVC)
                                                     name:@"appDidBecomeActive"
                                                   object:nil];

        // Custom initialization
    }
    return self;
}

-(void)openLastVC
{
    NSLog(@"val ==%@",[[NSUserDefaults standardUserDefaults] valueForKey:@"lastVC"]);

    if ([[[NSUserDefaults standardUserDefaults] valueForKey:@"lastVC"] isEqualToString:@"GhachakViewController"]) {
        GhachakViewController *gvc=[[GhachakViewController alloc] initWithNibName:@"GhachakViewController" bundle:nil];
        [self.navigationController pushViewController:gvc animated:NO];
    }
}

May this help you....

Upvotes: 2

Lukas Kukacka
Lukas Kukacka

Reputation: 7714

Yes, both cases are possible.

On crash, you can use UncaughtExceptionHandler to perform some code. In you app delegate, register you handler like this:

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

NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
//  Other didFinishLaunchingWithOptions code

And add your handler method to the same .m file

void uncaughtExceptionHandler(NSException *exception)
{
    //  App crashed, save last selected tabbar index to the to the NSUserDefaults
    [[NSUserDefaults standardUserDefaults] setInteger:tabBarController.selectedIndex forKey:@"LastSelectedTabbarIndex"];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

While app runs, to keep track of last selected tab bar controller, use UITabBarControllerDelegate and save newly selected tabbar's index to NSUserDefaults. Short example:

- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
    NSUInteger tabIndex = [[tabBarController viewControllers] indexOfObject:viewController];

    //  I have newly selected index, now save it to the NSUserDefaults
}

This code will save last selected tabbar's index to the NSUserDefaults every time tabbar's selected index changes.

Finally, when you app starts (in your didFinishLaunchingWithOptions), read last saved tabbar index from NSUserDefaults and set tabbar's selected index accordingly

self.tabBarController.selectedIndex = lastSelectedIndexFromDefaults;

Edit: If you also need to restore UINavigationControllers controllers stack, its pretty difficult task. I give you just a quick overview what comes to my mind.

There are 2 cases:

  • You have custom view controllers initializers and need to pass custom object to those controllers - In this case, its almost impossible (in some reasonable time) implement this
  • You use only -init or -initWithNibName...: to initialize view controllers in navigation stack. You could enumerate controllers from the root UINavigationController of the tab, get their classes names using NSStringFromClass and save them to NSUserDefaults. On apps start, you would reverse procedure (initialize controllers using their names strings read from NSUserDefaults using something like this: UIViewController *vc = [[NSClassFromString(@"aa") alloc] init];).

Upvotes: 3

amar
amar

Reputation: 4343

I understand you are ok with the code part so i will just give my suggestion

on viewDidLoad of every view controller set a nsuserdefault value of the top most object on navigation array.

if their are not too many branches then you can manage the push at root view controller easily

Upvotes: 2

Related Questions