gpt4 book ai didi

ios - 如何确保 View Controller 在 segueing 时不会重新加载?

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:02:33 25 4
gpt4 key购买 nike

我已经尝试了几个开源滑动菜单导航,它们模拟了 Facebook、Gmail 应用程序中的导航菜单(ViewDeckMFSideMenuSWRevealViewController),并且遇到了同样的问题,无论何时我继续进入另一个基于菜单选择的 ViewController,然后返回到原始 VC,你的 VC 总是重新加载,因此之前以编程方式添加的任何 subview 都消失了。即使我只是从菜单中选择相同的 VC,情况也是如此——它仍然会被加载。我试图在 App Delegate 中保留指向 View Controller 的强指针(通过实例化该 View 的属性),但这并没有解决问题?还有其他解决方法吗?谢谢!

我目前正在使用 SWRevealViewController,我的 Storyboard 也是这样设置的。

enter image description here

更新以及对我有用的内容:

最终,一切都与 MFSideMenu 和 danh 的建议一起工作,以将我感兴趣的 Controller 保留在导航堆栈中。

这是我选择非主视图 Controller 的代码

- (IBAction)buttonForNonPrimaryVC:(UIButton *)sender
{

someVC *someVC = [self.storyboard instantiateViewControllerWithIdentifier:@"someIdentifier"];
UINavigationController *navigationController = self.menuContainerViewController.centerViewController;
[navigationController pushViewController:someVC animated:NO];
[self.menuContainerViewController setMenuState:MFSideMenuStateClosed];

}

对于主视图 Controller 的选择:

- (IBAction)primaryVCTapped:(UIButton *)sender {

if ([[[self.menuContainerViewController.centerViewController viewControllers] lastObject] isKindOfClass: [primaryVC class]] || [[self.menuContainerViewController.centerViewController viewControllers] count] < 2){
//Do nothing
} else {
[self.menuContainerViewController.centerViewController popViewControllerAnimated:NO];
}
[self.menuContainerViewController setMenuState:MFSideMenuStateClosed];
}

最佳答案

特别是对于 SWRevealViewController,重用 View Controller 的实例实际上非常简单,不需要修改 SWRevealViewController。

在您指定的 MenuViewController(负责在您希望显示菜单项的 View Controller 时调用 segues 的 View Controller )中,创建一个 View Controller 缓存。这将用于存储通过 segue 创建的 View Controller 实例:

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

然后我检查 View Controller 缓存是否存在任何 View Controller 。如果是这样,请执行您通常在 prepareForSegue:sender: 中执行的 View Controller 交换(您应该在首次设置 SWRevealViewController 时将此代码段粘贴到那里)。如果它不存在,则正常执行 segue(这将创建一个新实例)。

现在剩下的就是修改您的 prepareForSegue:sender: 方法以在缓存中存储对实例化 View Controller 的引用:

- (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 上使用标识符,以便识别它们以进行缓存。

这种方法的一个限制是它只缓存从菜单 View Controller 中使用 segues 调用的 View Controller 。您会注意到,为第一个可见 View Controller 选择菜单项将导致它从头开始重新加载(因为它尚未缓存)。之后的任何时候,它都应该与缓存一起工作。我想象将缓存转移到位于 Storyboard 中的菜单设置之前的 SWRevealController 将缓解这种情况。您可以通过对其进行子类化来做到这一点。

关于ios - 如何确保 View Controller 在 segueing 时不会重新加载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20083675/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com