• OC 基础 控制器的跳转 Push + Present(源码)


    一直觉得自己写的不是技术,而是情怀,一个个的教程是自己这一路走来的痕迹。靠专业技能的成功是最具可复制性的,希望我的这条路能让你们少走弯路,希望我能帮你们抹去知识的蒙尘,希望我能帮你们理清知识的脉络,希望未来技术之巅上有你们也有我。

    前言

    今年简单说一下push跟present的用法。不管是push还是present,如果回退的时候按照原来的路径走回去的话就很简单的,但是如果回退的时候不按照原来的路径走的话就需要处理一下,所以今天的就记录了一个我之前开发中遇到的需求

    正题

    push

    最常用的方法:

    [self.navigationController pushViewController:BVC animated:YES];
    
    • 1

    present

    [self presentViewController:BVC animated:YES completion:nil];
    
    • 1

    modal控制器出来的方式在ios13.之前是默认是全屏覆盖的,现在默认是卡片的形式弹出来的,如果需要想以前的方式弹出来的话需要设置一下:有空的话可以进去枚举值里面去看一下,一个一个调试一下。

    vc.modalPresentationStyle = UIModalPresentationFullScreen;
    
    • 1

    1.使用present弹出控制器的时候,有时候需要需要再push,如果无法push的话present出来的控制器需要添加一个导航栏控制器.才能进行跳转.
    2.present出来的控制器可以添加到跟控制器里面.
    在这里插入图片描述

    UIModalPresentationFullScreen 是下面图片的效果
    在这里插入图片描述
    现在ios13以上默认就是下面的效果
    在这里插入图片描述

    这篇文章就想记录3个问题,可能在开发中会用到:

    需求1:

    需求1源码地址

    请添加图片描述

    1.控制器A跳到控制器B,控制器B跳到控制器C,然后在控制器C点击返回按键,返回来A控制器,过程不经过B控制器,我们要把B控制器移除。
    在这里插入图片描述
    实现的方法是在B控制器跳去C控制器的时候,push完把B控制器从栈中移除。
    在这里插入图片描述

    -(void) BBtnClick{  
      CViewController *CVC = [[CViewController alloc]init];
      [self.navigationController pushViewController:CVC animated:YES];
      NSMutableArray *tempMarr = [NSMutableArray arrayWithArray:self.navigationController.viewControllers];
      [tempMarr removeObject:self];
      [self.navigationController setViewControllers:tempMarr animated:YES];
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    需求2:

    需求2跳去任意控制器源码地址

    请添加图片描述

    1.控制器A跳到控制器B,控制器B跳到控制器C,C跳去D ,D跳去E,然后在E控制器返回去ABCD控制器都可以。
    在这里插入图片描述
    在这里插入图片描述

    -(void) EBtnClick{  
      for (UIViewController *controller in self.navigationController.viewControllers) {
        if ([controller isKindOfClass:[BViewController class]]) {
          BViewController *vc = (BViewController *)controller;
          [self.navigationController popToViewController:vc animated:YES];
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    需求3:

    需求3源码地址
    请添加图片描述

    控制器A跳去B, B跳去C, C跳去E,E返回时不是C,而是D但D在push时没有出现过的,D最后返回C, C返回就是B,B就到A
    在这里插入图片描述
    关键代码:跳去D控制器之后把E控制器添到导航栏的栈中
    在这里插入图片描述

    -(void) CBtnClick{  
        NSMutableArray *tempMarr = [NSMutableArray arrayWithArray:self.navigationController.viewControllers];
        [tempMarr addObject:[DViewController new]];
        [self.navigationController setViewControllers:tempMarr animated:NO];  
        EViewController *EVC = [[EViewController alloc]init];
        [self.navigationController pushViewController:EVC animated:YES];  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    需求4:

    需求4:(OC)Push+Present控制器跳转源码地址
    请添加图片描述

    在下面tabbar里的home,new, blower3个控制器里面通过present出PlayerVC控制器,在PlayerVC控制器dismiss回去的时候不是之前进来的home,new或者blower,而是albumvc歌曲列表控制器,然后里面点击pop返回的时候在回去home,new或者blower。PlayerVC控制器是modal出来的。而albumvc歌曲列表控制器是需要我们添加到导航栏的栈里面的。

    这个需求在开发音乐App的时候会用到,因为有一个迷你播放器会游离于整个项目,点击底部迷你播放器present整个播放器详情上来,然后有一个回退按键,点击回到歌曲列表。

    在这里插入图片描述
    在这里插入图片描述

    需求5:(常用)

    做电商项目的时候经常遇到这样的一个需求,从首页 -> 商品列表 -> 商品详情 -> 订单详情 -> 付款页面 ,走到这里,导航栏控制器已经添加了多个控制器到栈去里面了,在这个时候如果不进行付款的话,不会按照之前的路径返回的,如果要求我们直接返回到首页里,但是我们并不知道我们跳了多少个控制器,这个时候需要我们通过递归的方式把除了第一控制器(首页)和最后一个控制器(付款成功页),意外的所有页面都删除它。然后再pop回到首页里面。

    在这里插入图片描述

    请添加图片描述

    注意:我们可以在push到最后一个控制器的时候,就是倒数第二个页面,删除控制器,也可以在最后一个页面点击pop回来之前删除控制器。下面OC得代码是倒数第二个控制器push之后删除控制器的,swift的代码是pop的时候才删除控制器。

    OC

    OC-递归删除控制器-pop返回控制器
    在最后一个页面新建一个存储导航栏数组

    @property (nonatomic,strong) NSMutableArray<UIViewController *> *muArr;
    
    • 1

    点击按键的方法

    #pragma mark - 支付宝 支付成功后的处理
    -(void)paySuccessDispose{
      [self.navigationController pushViewController:orderVC animated:YES];
      
      //使用递归删除多余的控制器
      self.muArr = [NSMutableArray arrayWithArray:self.navigationController.viewControllers];
      [self removeVC];
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    递归删除控制器的方法

    //删除多余的控制器
    -(void)removeVC{
      if (self.muArr.count > 2) {
        [self.muArr removeObjectAtIndex:self.muArr.count-2];
      }else{
        [self.navigationController setViewControllers:self.muArr animated:YES];
        return;
      }
      //递归
      [self removeVC];
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    Swift

    Swift-递归删除控制器-pop返回控制器
    在最后一个页面新建一个存储导航栏数组

    var muArr = [UIViewController]()
    
    • 1

    点击按键的方法

    func onClick() {
    	guard let self = self else { return }
    	guard let nav = self.navigationController else { return }
    	self.muArr = nav.viewControllers
    	self.removeVC()
    	self.navigationController?.popViewController(animated: true, nil)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    递归删除控制器的方法

    //删除多余的控制器
    func removeVC() {
        if muArr.count > 2 {
            muArr.remove(at: muArr.count - 2)
        } else {
            self.navigationController?.setViewControllers(muArr, animated: false)
            return
        }
        removeVC()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • 相关阅读:
    spring-transaction源码分析(5)TransactionInterceptor事务拦截逻辑
    etcdctl-管理操作etcd集群
    『力扣每日一题07』字符串最后一个单词的长度
    基于ranger的kafka权限控制
    【灵动 Mini-G0001开发板】+Keil5开发环境搭建+ST-Link/V2程序下载和仿真+4颗LED100ms闪烁。
    buuctf_练[CSAWQual 2019]Web_Unagi
    如何自己制作电子杂志
    elasticsearch索引的数据类型以及别名的使用
    Chinese ​(Simplified)​ Language Pack / 中文语言包插件
    Android中内存泄漏的检测,解决方案以及示例
  • 原文地址:https://blog.csdn.net/weixin_38716347/article/details/126587628