State Preservation for View Controllers with Custom Delegates or Data Sources

倾然丶 夕夏残阳落幕 提交于 2019-12-03 15:15:32

You are right this is possible to do from the application-delegate level with application:viewControllerWithRestorationIdentifierPath:coder:, but you need to be careful/cleaver in how you do this!

The goal here is to return a TNTLoginViewController during the state restoration process with its delegate set to its parent.

First you must create a TNTLoginViewController object. You mentioned a storyboard so I will load it from there. I will assume that you have a fairly standard setup with a Main.storyboard file, and the identity properly set in the Identity Inspector.

TNTLoginViewController * loginViewController = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"loginViewController"];

Next you need to set its delegate to a parent. I am going to assume that there is a UINavigationController connecting this model. To find this from the application-delegate object you will need to dig into its window property.

The window property is a UIWindow object which has another property called rootViewController. This is a UIViewController object. Since I am assuming there is a UINavigationController connecting your model you will need to typecast this UIViewController to a UINavigationViewController (I would place the link I cannot at my current reputation level).

Now you can use the topViewController property the controller at the top of your navigation stack which is what you want to set as your delegate! If not then you can navigate your UINavigationController object for which object you want as your delegate.

And remember, since you are setting a delegate from the application-delegate level you might need to specify your protocol here to avoid vagueness.

To implement these last four steps in code will look something like this.

loginViewController.delegate = (id <TNTLoginViewControllerDelegate>)((UINavigationController *) self.window.rootViewController).topViewController;

And then you can return your TNTLoginViewController with its delegate properly set!

Make sure not to forget the implications of using application:viewControllerWithRestorationIdentifierPath:coder:. You only want to do this for the case of restoring your TNTLoginViewController. Luckily you can check for this with the identifierComponents argument which is passed in. Compare this to your identity name in the Identity Inspector and return nil if they do not match.

Your final method in the AppDelegate.m file will look something like this.

- (UIViewController *)application:(UIApplication *)application viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents coder:(NSCoder *)coder
{
if ([[identifierComponents lastObject] isEqualToString:@"loginViewController"]) {
    TNTLoginViewController * loginViewController = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"loginViewController"];

    loginViewController.delegate = (id <TNTLoginViewControllerDelegate>)((UINavigationController *) self.window.rootViewController).topViewController;

    return loginViewController;
}

return nil;
}

I hope this helps!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!