deepak kumar deepak kumar - 5 months ago 31
Objective-C Question

keep saved state of view controller in SWRevealController in iOS?

I am using

SWRevealController
in my app.I have one
MainController
as "HOME" which is shown when app launches. Now I have
textfield
& other controls on that screen. When i switch to another screen & come back to "Home" then all data on "Home" screen is gone then. It does not show any data there.I want to keep it's state saved. Now i want to keep that view controller in stack so that when i come back to this
viewcontroller
it remains in stack & other view controller are just popped out.Please explain how can i do that?

I am using below code for this.

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell=[self.tableView cellForRowAtIndexPath:indexPath];
if(indexPath.row==0)
{
[self performSegueWithIdentifier:@"home" sender:cell];
[cell setSelected:YES];
}

else if(indexPath.row==1)
{
[self performSegueWithIdentifier:@"settings" sender:cell];
}

else if(indexPath.row==2)
{
[self performSegueWithIdentifier:@"help" sender:cell];
}
else if(indexPath.row==3)
{
[self performSegueWithIdentifier:@“about” sender:cell];
}

}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSLog(@"Segue");
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
UINavigationController *destViewController = (UINavigationController*)segue.destinationViewController;
destViewController.title = [[titles objectAtIndex:indexPath.row] capitalizedString];
if([segue.identifier isEqualToString:@"settings"])
{
self.revealViewController.navigationItem.title = @"settings";

}
else if([segue.identifier isEqualToString:@"help"])
{
self.revealViewController.navigationItem.title = @"help";
}
else if([segue.identifier isEqualToString:@"about"])
{
self.revealViewController.navigationItem.title = @"about";
}

if([segue isKindOfClass:[SWRevealViewControllerSegue class]])
{
SWRevealViewControllerSegue *swSegue = (SWRevealViewControllerSegue*) segue;

swSegue.performBlock = ^(SWRevealViewControllerSegue* rvc_segue, UIViewController* svc, UIViewController* dvc) {
UINavigationController* navController = (UINavigationController*)self.revealViewController.frontViewController;
[navController setViewControllers: @[dvc] animated: NO ];
[self.revealViewController setFrontViewPosition: FrontViewPositionLeft animated: YES];



};

}

}


EDIT:

It tried below code & it is working in case i switch between "Home" & other screens twice.

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell=[self.tableView cellForRowAtIndexPath:indexPath];
if(indexPath.row==0)
{
if(objMainController != nil)
{
UINavigationController* navController = (UINavigationController*)self.revealViewController.frontViewController;
[navController setViewControllers: @[objMainController] animated: NO ];
[self.revealViewController setFrontViewPosition: FrontViewPositionLeft animated: YES];
}
else
{
[self performSegueWithIdentifier:@"home" sender:cell];
[cell setSelected:YES];
}

}
else if(indexPath.row==1)
{

[self performSegueWithIdentifier:@"settings" sender:cell];
}
else if(indexPath.row==2)
{

[self performSegueWithIdentifier:@"help" sender:cell];
}
else if(indexPath.row==3)
{

[self performSegueWithIdentifier:@"about" sender:cell];
}


}


in prepareforsegue

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSLog(@"Segue");
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
UINavigationController *destViewController = (UINavigationController*)segue.destinationViewController;
destViewController.title = [[titles objectAtIndex:indexPath.row] capitalizedString];
if([segue.identifier isEqualToString:@"settings"])
{
self.revealViewController.navigationItem.title = @"settings";

}
else if([segue.identifier isEqualToString:@"about"])
{
self.revealViewController.navigationItem.title = @"about";
}
else if([segue.identifier isEqualToString:@"help"])
{
self.revealViewController.navigationItem.title = @"help";
}


if([segue isKindOfClass:[SWRevealViewControllerSegue class]])
{
SWRevealViewControllerSegue *swSegue = (SWRevealViewControllerSegue*) segue;

swSegue.performBlock = ^(SWRevealViewControllerSegue* rvc_segue, UIViewController* svc, UIViewController* dvc) {
UINavigationController* navController = (UINavigationController*)self.revealViewController.frontViewController;
if([segue.identifier isEqualToString:@"home"])
{
objMainController = (MainViewController*)destViewController;
self.revealViewController.navigationItem.title = @"home";
[navController setViewControllers: @[objMainController] animated: NO ];
}
else
{
[navController setViewControllers: @[dvc] animated: NO ];

}

[self.revealViewController setFrontViewPosition: FrontViewPositionLeft animated: YES];
};

}

}

Answer

Every time you perform a segue, a new UIViewController instance is created for you inside destinationViewController and you need to keep a reference to this once it is created (very first time).

Step #1

Keep a reference to all the UIViewController instances you need to keep state saved for-

SettingsViewController* objSettingsVC;

Step #2

Don't perform a segue if the instance for the screen you need to navigate to has been created earlier-

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:indexPath];

    if(indexPath.row == 1)
    {
        if(objSettingsVC != nil)
        {
            UINavigationController* navController = (UINavigationController*)self.revealViewController.frontViewController;
            [navController setViewControllers: @[objSettingsVC] animated: NO ];
            [self.revealViewController setFrontViewPosition: FrontViewPositionLeft animated: YES];
        }
        else
        {
            [self performSegueWithIdentifier:@"settings" sender:cell];
        }
    }
}

Step #3

Keep the UIViewController instance in a variable to later refer to it as soon as it's created for the first time inside prepareForSegue: -

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    UINavigationController* destViewController = (UINavigationController*)segue.destinationViewController;

    if([segue.identifier isEqualToString:@"settings"])
    {
        objSettingsVC = (SettingsViewController*)destViewController;
        self.revealViewController.navigationItem.title = @"Settings";
    }
}

Hope it helps.

UPDATE:

As discussed below in the comments, you also need to keep the initialViewController instance in a variable. Here's how you can do it.

AppDelegate.h

#import <UIKit/UIKit.h>
#import "ViewController.h"

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) ViewController *objMainController;


@end

ViewController.m

#import "ViewController.h"
#import "AppDelegate.h"

@interface ViewController ()

@end

@implementation ViewController

-(void)viewDidLoad
 {
     [super viewDidLoad];

     AppDelegate* appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
     appDelegate.objMainController = self;
 }


 @end

This isn't a very good approach, but it will get you going. Your AppDelegate shouldn't be a part of all this navigation logic, you should keep this in a separate object responsible for your app navigation. Perhaps your SideTableViewController in your case.

Comments