iOS---APP状态恢复--UIStateRestoration

UIStateRestoration是iOS6开始的系统自带,用户存储和恢复APP的界面和状态,使APP在后台被系统杀死的情况下,再次打开给用户造成一种APP一直在运行的假象,当然用户肯定是愿意看到这些的,因为不需要重新启动APP就能使用,作为一个公司的APP产品来说,也是提高用户体验的一部分。

下面是所涉及的方法:

//根据已注册的RestorationId列表,来返回对应的控制器
//- (nullable UIViewController *) application:(UIApplication *)application viewControllerWithRestorationIdentifierPath:(NSArray<NSString *> *)identifierComponents coder:(NSCoder *)coder{
//
//}

//判断是否需要存储APP的状态,这在APP进入到后台时会触发,可以在此方法中判断是否有必要对APP的状态进行存储。
-(BOOL)application:(UIApplication *)application shouldSaveSecureApplicationState:(NSCoder *)coder
{
return YES;
}

//判断是否需要恢复APP的状态,这个在APP重新启动时会触发,但需要注意的一点是,这个方法会在AppDelegate的willFinishLaunchingWithOptions和didFinishLaunchingWithOptions方法中直接调用,如果该处返回YES,则会执行一系列状态恢复的操作,包括初始化并跳转到控制器等,所以如果没有使用StoryBoard的话,我们创建Window以及一些必要的初始化方法应该在willFinishLaunchingWithOptions中执行。在返回YES之前,还有一些需要注意的事项,例如权限操作、登录失效等,这些情况下都不应该使APP状态得到恢复
-(BOOL)application:(UIApplication *)application shouldRestoreSecureApplicationState:(NSCoder *)coder{
return YES;
}

//APP将要对当前状态encode并存储起来,encode包括控制器的控件以及数据,还会有一份当前界面的截图,用于状态恢复时替换启动图的。所以在encode之前,需要存储一些无关紧要的数据,官方建议存储一些与界面关联性不大的东西。如果没有,那就放一个空方法。

  • (void)application:(UIApplication *)application willEncodeRestorableStateWithCoder:(NSCoder *)coder{

}

//APP重新启动后调用,在第三个方法返回YES之后并且在APP恢复所涉及的控制器的viewDidLoad之后,viewWillAppear之前,之后才是didFinishLaunching-WithOptions。也就是说,当APP重新启动时,这些方法的调用顺序是:application:didDecodeRestorableStateWithCoder→viewDidLoad→viewWillAppear→didFinishLaunching-WithOptions
-(void)application:(UIApplication *)application didDecodeRestorableStateWithCoder:(NSCoder *)coder{

[[UIApplication sharedApplication]extendStateRestoration];
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(globalQueue, ^{
   
    dispatch_async(dispatch_get_main_queue(), ^{
        [[UIApplication sharedApplication]completeStateRestoration];
    });
});

}

//该方法在系统准备存储APP状态时调用,可以在该方法中加上一些自定义的值存储,方便后面状态恢复时直接取用。注意这里是重写UIViewController的方法,不是对协议的实现,需要调用super的该方法。
-(void)encodeRestorableStateWithCoder:(NSCoder *)coder{

[super encodeRestorableStateWithCoder:coder];

// coder encodeObject:<#(nullable id)#> forKey:@"key"//存值
}

//APP状态恢复时decode调用的,刚才存储的自定义值,可以在该方法中重新获得。注意也需要调用super的该方法。
-(void)decodeRestorableStateWithCoder:(NSCoder *)coder{
[super decodeRestorableStateWithCoder:coder];
// [coder decodeObjectForKey:@"key"];//取值
}

//表明此时APP的状态恢复以及完成,我们的控制器已经创建好了,所需的数据也已经拿到了,所以可以在该方法中进行一些例如列表刷新的操作。
-(void)applicationFinishedRestoringState{

}

//值得注意的是,只要我们给restorationClass属性赋值,则其所属类不管是纯代码还是StoryBoard,都会通过下面这个类方法来获取状态恢复时所需要的实例对象
//+ (nullable UIViewController *) viewControllerWithRestorationIdentifierPath:(NSArray<NSString *> *)identifierComponents coder:(NSCoder )coder{
//
// AppStateRestorationViewController
vc =[[AppStateRestorationViewController alloc]init];
// return vc;
//}

//基于UINavigationController的,并且没有基于StoryBoard而是纯代码实现的,那这种情况需要如何实现状态恢复呢?每个控制的类方法viewControllerWithRestorationIdentifierPath都是返回自己本身,而UINavigationController的初始化方法还需要一个根控制器对象,这该如何实现呢?那么就需要让这个控制器实现UIViewControllerRestoration协议,并在这个协议方法中直接返回自身,不用带根控制器。

  • (nullable UIViewController *) viewControllerWithRestorationIdentifierPath:(NSArray<NSString *> *)identifierComponents coder:(NSCoder *)coder{

    UINavigationController* nav =[[UINavigationController alloc]init];
    return nav;
    }