SWRevealViewControllerSegue,重用Viewcontrollers

我正在使用SWRevealViewController,我正在使用自定义的segue,我注意到每次执行segue SWRevealViewController创build一个全新的目标控制器实例,有没有办法让SWRevealViewController重用viewcontrollers?

重用视图控制器的实例其实很简单,并且不需要修改SWRevealViewController。

在您指定的MenuViewController中(视图控制器负责在您希望显示菜单项的视图控制器时调用segues),请创build一个视图控制器caching。 这将被用来存储视图控制器实例时,通过segue创build:

@property (nonatomic, strong) NSMutableDictionary *viewControllerCache; 

稍后我们会在需要时进行初始化。

每当你select菜单项时,不要直接调用segue,而是调用一个方法来检查caching:

 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { // your logic will vary here, this is just an example switch(indexPath.row) { case 0: [self showViewControllerForSegueWithIdentifier:@"showSomething" sender:nil]; break; default: break; } } 

这个caching检查方法可能看起来像这样:

 - (void)showViewControllerForSegueWithIdentifier:(NSString *)identifier sender:(id)sender { NSString *cacheKey = [identifier stringByAppendingFormat:@":%@", sender]; UIViewController *dvc = [self.viewControllerCache objectForKey:cacheKey]; if(dvc) { NSLog(@"reusing view controller from cache"); UINavigationController* navController = (UINavigationController*)self.revealViewController.frontViewController; [navController setViewControllers: @[dvc] animated: NO ]; [self.revealViewController setFrontViewPosition: FrontViewPositionLeft animated: YES]; } else { NSLog(@"creating view controller from segue"); [self performSegueWithIdentifier:identifier sender:sender]; } } 

在这种情况下,我在caching中创build一个键作为segue名称和sender参数的组合。 为了举例,我假设发件人是一个string。 发件人参数很可能不是一个string,所以你应该做一些检查,以确保它不会崩溃。

如果有任何视图控制器存在,我然后检查视图控制器caching。 如果是这样,在prepareForSegue:sender:执行你通常做的视图控制器交换(当你第一次设置你的SWRevealViewController时,你会在这里粘贴这个代码片段)。 如果不存在,按正常方式执行segue(这将创build一个新的实例)。

现在剩下的就是修改prepareForSegue:sender:方法来存储对caching中实例化视图控制器的引用:

 - (void) prepareForSegue:(UIStoryboardSegue *) segue sender:(id) sender { if([segue.identifier isEqualToString:@"showSomething"]) { // do whatever you wish to the destination view controller here // ... } // this part should be very familiar if ( [segue isKindOfClass: [SWRevealViewControllerSegue class]] ) { SWRevealViewControllerSegue *swSegue = (SWRevealViewControllerSegue*) segue; swSegue.performBlock = ^(SWRevealViewControllerSegue* rvc_segue, UIViewController* svc, UIViewController* dvc) { // cache the view controller if(self.viewControllerCache == nil) self.viewControllerCache = [NSMutableDictionary dictionary]; NSString *cacheKey = [segue.identifier stringByAppendingFormat:@":%@", sender]; [self.viewControllerCache setObject:dvc forKey:cacheKey]; // the rest remains as before UINavigationController* navController = (UINavigationController*)self.revealViewController.frontViewController; [navController setViewControllers: @[dvc] animated: NO ]; [self.revealViewController setFrontViewPosition: FrontViewPositionLeft animated: YES]; }; } } 

请注意,我只是将2-3行添加到prepareForSegue:sender: ,这不会干扰您现有的设置。 可能没有设置segue标识符,这会导致崩溃。 你应该在你的segues上使用标识符,以便你可以识别它们的caching。

这种方法的一个限制是,它只caching从菜单视图控制器调用segues的视图控制器。 您会注意到,为第一个可见视图控制器select菜单项会导致它从头开始重新加载(因为它还没有被caching)。 任何时候,它应该与caching工作。 我想象一下,在故事板中的菜单设置之前,将caching切换到SWRevealController将缓解这种情况。

您可以使用UITabBarController存储和重用ViewControllers只需通过sw_front segue使您的UITabBarController frontViewController,然后从后视图控制器切换viewControllers

 override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { //get tabBarController let tabBarVC = revealViewController().frontViewController as? UITabBarController //show selected ViewController tabBarVC.selectedIndex = indexPath.item revealViewController().revealToggle(animated: true) }