SWRevealViewController

SWRevealViewController

本文介绍了SWRevealViewControllerSegue,重用Viewcontrollers的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am working with SWRevealViewController, and I am using the custom segue, I notice that everytime segue is performed SWRevealViewController creates a brand new instance of the destination controller, is there a way to have SWRevealViewController reuse viewcontrollers?

推荐答案

重用视图控制器实例实际上非常简单,并且不需要修改SWRevealViewController.

Reusing instances of your view controllers is actually very straightforward, and it doesn't require modifying SWRevealViewController.

在您指定的MenuViewController(无论何时您希望显示菜单项的视图控制器,负责调用segue的视图控制器)中,创建一个视图控制器缓存.每当通过segue创建视图控制器实例时,这将用于存储它们:

In your designated MenuViewController (the view controller responsible for invoking segues whenever you wish to show a menu item's view controller), create a view controller cache. This will be used to store view controller instances whenever they are created via segue:

@property (nonatomic, strong) NSMutableDictionary *viewControllerCache;

我们稍后将在需要时进行初始化.

We'll initialise this later when needed.

无论何时响应选择菜单项,而不是直接调用segue,都调用一种方法来检查缓存:

Whenever you respond to selecting menu items, instead of invoking a segue directly, call a method instead that checks the cache:

- (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;
    }

}

此缓存检查方法可能类似于以下内容:

This cache checking method could look something like this:

- (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参数很可能不是字符串,因此您应该做一些检查以确保它不会崩溃.

In this scenario, I create a key in the cache as a combination of the segue name and the sender parameter. I'm assuming the sender is a string here for the sake of an example. It's quite possible that the sender parameter is not a string, so you should probably do some checking to ensure it doesn't crash.

然后我检查视图控制器缓存是否存在任何视图控制器.如果是这样,请执行您通常在 prepareForSegue:sender:中执行的视图控制器交换操作(当您初次设置SWRevealViewController时,您会在该位置粘贴该代码段).如果不存在,请照常执行segue(这将创建一个新实例).

I then check the view controller cache if any view controller exists. If so, perform the view controller swapping you normally do in prepareForSegue:sender: (you would have pasted this snippet in there when you first set up your SWRevealViewController). If it doesn't exist, perform the segue as normal (which will create a new instance).

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

All that's left now is to modify your prepareForSegue:sender: method to store a reference to the instantiated view controller in the cache:

- (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标识符,这将导致崩溃.您应该在序列中使用标识符,以便可以标识它们以进行缓存.

Notice how I'm just appending 2-3 lines to prepareForSegue:sender:, which shouldn't interfere with your existing setup. It's possible that the segue identifier isn't set, which will result in a crash. You should use identifiers on your segues so you can identify them for caching.

此方法的局限性在于,此方法仅缓存使用菜单视图控制器中的segues调用的视图控制器.您会注意到,为第一个可见视图控制器选择菜单项将导致从头开始重新加载它(因为尚未缓存).在此之后的任何时间,它都应与缓存一起使用.我想将缓存转移到故事板上的菜单设置之前的SWRevealController可以减轻这种情况.

One limitation with this approach is that this only caches view controllers that were invoked with segues from the menu view controller. You'll notice that selecting the menu item for the first visible view controller will cause it to be reloaded from scratch (because it wasn't cached yet). Any time after that, it should work with the cache. I imagine shifting the caching to the SWRevealController that sits before your menu setup in the storyboard will alleviate this.

这篇关于SWRevealViewControllerSegue,重用Viewcontrollers的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-18 13:58