Is iOS state restoration possible in iOS library?

2020-04-10 03:44发布

问题:

I have a library with a storyboard and controller classes that implement iOS state preservation.

To launch the library from the main app's delegate, I use the following:

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

    self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
    [self.window makeKeyAndVisible];
    self.window.rootViewController = myLibrary.sharedInstance.firstController;

    return YES;
}

Then inside my library, firstController is created with:

- ( UIViewController * _Nullable ) firstController
{
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"libraryMain"
        bundle:[NSBundle bundleForClass:self.class]];

    return [storyboard instantiateViewControllerWithIdentifier:@"firstController"];
}

So far so good. It starts the library's view controller that uses the library's "libraryMain" storyboard.

In the main app's delegate, I've also added shouldSaveApplicationState and shouldRestoreApplicationState, both of which return YES.

When my app goes to the background, iOS correctly calls shouldSaveApplicationState in delegate and proceeds to call the library's controller's encodeRestorableStateWithCoder methods.

However, when it tries to restore, iOS correctly calls the main app delegate's shouldRestoreApplicationState method, but then immediately crashes with the following exception:

Exception occurred restoring state Could not find a storyboard named 'libraryMain' in bundle ... Main App.app

So iOS is looking for the libraryMain storyboard in the main app's bundle. How do I get iOS to look in the library's bundle? Or is it just not possible to implement state restoration in an iOS library?

Thanks!

回答1:

If the 'libraryMain' is a static library that you link to the main app, then it doesn't contain the storyboard files, and the iOS is missing the file in the main bundle (unless you specifically provide it).

The reason is that static libraries are archives of the compiled code, and the resources have to be included separately. In this case, you need to find a way to bundle your resources - either including the 'libraryMain' storyboard directly into the main app or creating a "resource" bundle.

If the 'libraryMain' is a framework with a storyboard file inside, then there are some workarounds.

The documentation about the state preservation notes that there are two places that iOS checks in order to restore the controller:

  1. viewControllerWithRestorationIdentifierPath:coder: of the restoration class (firstController class, in your question). Here you can create and configure the instance of the first controller
  2. application:viewControllerWithRestorationIdentifierPath:coder: of the app delegate. Here you can create the instance of the class based on the restoration path.

Both of the options above look like workarounds as I don't have the actual setup of your project to reproduce the problem.