我正在使用SWRevealViewController,我正在使用自定义segue,我注意到每次执行segue时SWRevealViewController都会创建一个全新的目标控制器实例,有没有办法让SWRevealViewController重用viewcontrollers?
解决方法
重用视图控制器的实例实际上非常简单,并且不需要修改SWRevealViewController.
在您指定的MenuViewController(负责在您希望显示菜单项的视图控制器时调用segue的视图控制器)中,创建一个视图控制器缓存.这将用于存储视图控制器实例,只要它们是通过segue创建的:
@property (nonatomic,strong) NSMutableDictionary *viewControllerCache;
我们稍后会在需要时对其进行初始化.
每当您响应选择菜单项时,不是直接调用segue,而是调用一个检查缓存的方法:
- (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; } }
此缓存检查方法可能如下所示:
- (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]; } }
在这种情况下,我在缓存中创建一个键作为segue名称和sender参数的组合.为了举个例子,我假设发送者是一个字符串. sender参数很可能不是字符串,所以你应该做一些检查以确保它不会崩溃.
然后,如果存在任何视图控制器,则检查视图控制器缓存.如果是这样,执行您通常在prepareForSegue:sender中执行的视图控制器交换:(当您第一次设置SWRevealViewController时,您将在此处粘贴此代码段).如果它不存在,则正常执行segue(这将创建一个新实例).
现在剩下的就是修改prepareForSegue:sender:方法来存储对缓存中实例化视图控制器的引用:
- (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]; }; } }
请注意我是如何在prepareForSegue:sender:中添加2-3行,这不应该干扰您现有的设置.可能没有设置segue标识符,这将导致崩溃.您应该在segue上使用标识符,以便识别它们以进行缓存.
这种方法的一个限制是,它仅缓存使用菜单视图控制器中的segue调用的视图控制器.您会注意到,为第一个可见视图控制器选择菜单项将导致从头开始重新加载(因为它尚未缓存).在此之后的任何时候,它都应该与缓存一起使用.我想将缓存转移到位于故事板中菜单设置之前的SWRevealController将缓解这种情况.