iOS 一键返回首页

2019-12-27  本文已影响0人  ZT_Story

随着业务越来越复杂,越来越繁多,甚至与web共舞
一键返回首页的情况就很常见了

最简单的方式是直接重新设置AppDelegate.window.rootViewController
但是这样做有小伙伴发现如果页面栈存在present的情况,会出现部分页面无法被释放,从而导致内存泄漏

所以,在页面栈繁杂,弹出页面方式奇奇怪怪的情况下,还能有条不紊的返回APP首页,使我们当下的需求
那么,如何才能安全的、不出错的返回首页呢,并且最好能保证体验良好?

答案是:原路返回,怎么出去就怎么回来

思路及代码实现

1、获取到当前的根视图,如果是UITabBarController做特殊处理

UIWindow *window = [(AppDelegate *)[UIApplication sharedApplication].delegate window];
    
UIViewController *rootController = [window rootViewController];
if ([rootController isKindOfClass:[UITabBarController class]]) {
    rootController = [(UITabBarController *)rootController selectedViewController];
}
UIViewController *presentedController = rootController;

2、找到所有的presentedViewController,包括UIViewControllerUINavigationController

NSMutableArray<UIViewController *> *presentedControllerArray = [[NSMutableArray alloc] init];
while (presentedController.presentedViewController) {
   [presentedControllerArray addObject:presentedController.presentedViewController];
   presentedController = presentedController.presentedViewController;
}

3、将所有找到的vc进行递归dismiss操作或popToRoot

if (presentedControllerArray.count > 0) {
   //把所有presented的controller都dismiss掉
   [self dismissControllers:presentedControllerArray topIndex:presentedControllerArray.count - 1 completion:^{
        [self popToRootViewControllerFrom:rootController];
   }];
} else {
   [self popToRootViewControllerFrom:rootController];
}

递归方法封装

- (void)dismissControllers:(NSArray<UIViewController *> *)presentedControllerArray topIndex:(NSInteger)index completion:(void(^)(void))completion
{
    if (index < 0) {
        completion();
    } else {
        [presentedControllerArray[index] dismissViewControllerAnimated:NO completion:^{
            [self dismissControllers:presentedControllerArray topIndex:index - 1 completion:completion];
        }];
    }
}

- (void)popToRootViewControllerFrom:(UIViewController *)fromViewController
{
    if ([fromViewController isKindOfClass:[UINavigationController class]]) {
        [(UINavigationController *)fromViewController popToRootViewControllerAnimated:NO];
    }
    if (fromViewController.navigationController) {
        [fromViewController.navigationController popToRootViewControllerAnimated:NO];
    }
}

这里有人可能会问,为什么不使用setRootViewController的方式返回?
如果有present的vc弹出,在setRoot的时候会造成一定的内存泄漏,如果流程多来几次,有可能产生很多不可预期的问题,所以,原路返回是最为稳妥和安全的一种方式。
欢迎大家分享自己的返回首页方案

借鉴:https://blog.csdn.net/yinyignfenlei/article/details/86167245

上一篇下一篇

猜你喜欢

热点阅读