Question

I need some help in picking the 'right' solution for the following 'problem'.

I use the new storyboard feature to link all the screens of my application together. Basically the structure drills down to:

[Navigation Controller] => [View Controller #1] => [Tabbar Controller] => [View Controller #2]*

**(and some other tabs which are for now not important)*

I have attached a segue (push) from the first View Controller (#1) to the View Controller behind the Tab Bar Controller. This push is triggered when the users presses something on the first controller and works fine.

// Execute preset segue
[self performSegueWithIdentifier:@"segueEventDetail" sender:self];

When the user (which is now in the View Controller #2) presses the back button in the navbar the user goes back. Suppose he now triggers the segue again, the second view controller is shown again but is now 'resetted' (empty). (I believe after reading several fora and articles this is standard behavior when using segue's because these destroy and reinitiliaze the view controller's every time?)

This (the view controller being resetted) poses a problem because the contents of the second view controller is dynamic (depend on a JSON response from the server) and thus it is 'needed' that the view controller remains intact (or is restored) when the user comes back.

I have found several sources (see bottom) describing the same issue, but the solutions vary and I need some help picking the right one.

Summarize:

  • How can I 'retain'/save the state of a View Controller when the users presses back, while preserving the use of Storyboard & preferably also Segue's

Own Thoughts:

#1 I'm now thinking of caching the JSON Response to my singleton class (and from there to a PLIST) and checking within the second view controller if this data is present and than rebuild the view after which I check for any new data (resume normal operation).

#2 Another one I'm thinking of is 'bypassing' the segue and manually handle the switch of views , partially explained in (Storyboard - refer to ViewController in AppDelegate) - Is this also possible?

But maybe there is an easier/better option?

http://www.iphonedevsdk.com/forum/iphone-sdk-development/93913-retaining-data-when-using-storyboards.html Storyboard - refer to ViewController in AppDelegate How to serialize a UIView?

Was it helpful?

Solution 2

For anyone coming across this (my) question in the future, this is how I ended up 'coding' it.

  • Open the storyboard and select your 'Tab Bar Controller' and open the Attributes Inspector

  • Fill in an 'identifier' in the field

  • With the first view controller (see scenario in original post) I create an global reference to the viewcontroller:

firstviewcontroller.h

@interface YourViewController : UIViewController {

    UITabBarController *tabController;

}

firstviewcontroller.m

//Fill the reference to the tabcontroller using the identifier
tabController = [self.storyboard instantiateViewControllerWithIdentifier:@"tabbar"];

Now to switch from the firstviewcontroller the following line can be used:

[[self navigationController] pushViewController:tabController animated:YES];

OTHER TIPS

Yess!! I got the solution. Do the following:

In you're .h file:

@property (strong, nonatomic) UITabBarController *tabController;

In you're .m file:

@synthesize tabController;

tabController = [self.storyboard instantiateViewControllerWithIdentifier:@"tabbar"];

The selected index is the tab you want to go

tabController.selectedIndex = 1;

[[self navigationController] pushViewController:tabController animated:YES];

This might be even more simple solution (without using properties - in fact, all your class instances don't need to know about their destination controllers, so just save it as static in the pushing function):

static UIVewController *destController = nil;
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
if (!storyboard) {
    DLog(Storyboard not found);
    return;
}
if (destController == nil) { //first initialisation of destController
    destController = [storyboard instantiateViewControllerWithIdentifier:@"{Your Destination controller identifyer}"];
    if(!destController) {
        DLog(destController not found)
        return;
    }
}
//set any additional destController's properties;
[self.navigationController pushViewController:destController animated:YES];

p.s. DLog is just my variation of NSLog.

But it's really interesting how to do this with segue?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top