iOS 一键返回首页

随着业务越来越复杂,越来越繁多,甚至与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

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1 Fragment 懒加载是什么意思? 所谓懒加载,即Fragment 的 UI 对用户可见时才加载数据。 以前...
    随心随性_0a25阅读 139评论 0 0
  • 2018年3月24日 新闻话题打卡 “别让你的孩子不愿学医” 前几年的数据显示,美国83%的医生家庭的孩子首选学医...
    SEHUN_NP阅读 226评论 0 0