Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Save and restore UINavigation stacks to reconnect

I am currently having a hard time understanding what I should use to save and restore my app state.

I am using a storyboard and I have quite some ViewControllers, and I want to save all my navigation stacks when the app is terminated to be able to restore all the navigation when the user relaunch the application.

I am using a UINavigationController with another UINavigationController inside it just for information.

I found this and read this over and over : https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/PreservingandRestoringState.html#//apple_ref/doc/uid/TP40007457-CH28-SW34

(Required) Assign restoration identifiers to the view controllers whose configuration you want to preserve; see Tagging View Controllers for Preservation.

(Required) Tell iOS how to create or locate new view controller objects at launch time; see Restoring View Controllers at Launch Time.

Then I added a RestorationId on all my ViewControllers but I don't understand what I should do for the second part as when I add viewControllerWithRestorationIdentifierPath methods I don't pass inside.

I also tried to save the navigation.viewcontrollers into the NSUserDefaults in order to use them again when the user restart the app using the code :

+(NSArray *) getNavStatus
{
    NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
    id objectSaved;
    if( (objectSaved = [preferences objectForKey:navStatusKey]) != nil)
        return [NSKeyedUnarchiver unarchiveObjectWithData:objectSaved];
    else
        return nil;
}

+(BOOL) saveNavStatus:(UINavigationController *) nav
{
    NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults];
    
    NSData *encodedObject = [NSKeyedArchiver archivedDataWithRootObject:nav.viewControllers];
    [preferences setObject:encodedObject forKey:navStatusKey];
    
    //  Save to disk
    return [preferences synchronize];
}

But when I get back in the app apple stats to tell me that the constraint ain't respected and that the app will crash and then when I add the viewControllers in the stack of my navigation it does crash :)

Any tips or help would be much appreciated. Thanks a lot

like image 786
Clad Clad Avatar asked Jul 13 '16 14:07

Clad Clad


1 Answers

Did you implement application:shouldRestoreApplicationState: and application: shouldSaveApplicationState: methods in application delegate. Hope the step blow can help you:

1. Set restoration identifiers

When assigning restoration identifiers, remember that all parent view controllers in the view controller hierarchy must have restoration identifiers too. Also include NavigationController and TabBar…

  • a. Assign a valid string to the view’s restorationIdentifier property.

  • b. Use the view from a view controller that also has a valid restoration identifier.

  • c. For table views and collection views, assign a data source that adopts the UIDataSourceModelAssociation protocol.

-

2. Tell application you want use State Preservation

Add the two methods to the application delegate.m file to required both saving and restoration of application state

    -(BOOL)application:(UIApplication *)application shouldRestoreApplicationState:(NSCoder *)coder
{
    return YES;
}

-(BOOL)application:(UIApplication *)application shouldSaveApplicationState:(NSCoder *)coder
{
    return YES;
}

3. Write and read Controller state

You Preservation Controller must adopt the UIStateRestoring protocol and use the methods of that protocol to write and read its state.

-(void)encodeRestorableStateWithCoder:(NSCoder *)coder
    {
        if (_textLabel.text.length > 0) {
            [coder encodeObject:_textLabel.text forKey:@"labelText"];
        }
        [super encodeRestorableStateWithCoder:coder];
    }

    -(void)decodeRestorableStateWithCoder:(NSCoder *)coder
    {
        _textLabel.text = [coder decodeObjectForKey:@"labelText"];
        [super decodeRestorableStateWithCoder:coder];
    }

4. Restore ViewController

Implement viewControllerWithRestorationIdentifierPath:coder: method of the associated restoration class to retrieve the view controller.

+ (nullable UIViewController *)viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents coder:(NSCoder *)coder{
    ViewControllerThree * restoreVc;
    UIStoryboard* storyBoard = [coder decodeObjectForKey:UIStateRestorationViewControllerStoryboardKey];
    if (storyBoard) {
        restoreVc = (ViewControllerThree*)[storyBoard instantiateViewControllerWithIdentifier:@"ViewControllerThree"];
        restoreVc.restorationIdentifier = [identifierComponents lastObject];
        restoreVc.restorationClass = [ViewControllerThree class];
    }
    return restoreVc;
}
like image 122
Stoull Avatar answered Nov 06 '22 16:11

Stoull