今年简单说一下push跟present的用法。不管是push还是present,如果回退的时候按照原来的路径走回去的话就很简单的,但是如果回退的时候不按照原来的路径走的话就需要处理一下,所以今天的就记录了一个我之前开发中遇到的需求
最常用的方法:
[self.navigationController pushViewController:BVC animated:YES];
[self presentViewController:BVC animated:YES completion:nil];
modal控制器出来的方式在ios13.之前是默认是全屏覆盖的,现在默认是卡片的形式弹出来的,如果需要想以前的方式弹出来的话需要设置一下:有空的话可以进去枚举值里面去看一下,一个一个调试一下。
vc.modalPresentationStyle = UIModalPresentationFullScreen;
1.使用present弹出控制器的时候,有时候需要需要再push,如果无法push的话present出来的控制器需要添加一个导航栏控制器.才能进行跳转.
2.present出来的控制器可以添加到跟控制器里面.
UIModalPresentationFullScreen 是下面图片的效果
现在ios13以上默认就是下面的效果
这篇文章就想记录3个问题,可能在开发中会用到:
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.控制器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];
}
}
}
控制器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];
}
在下面tabbar里的home,new, blower3个控制器里面通过present出PlayerVC控制器,在PlayerVC控制器dismiss回去的时候不是之前进来的home,new或者blower,而是albumvc歌曲列表控制器,然后里面点击pop返回的时候在回去home,new或者blower。PlayerVC控制器是modal出来的。而albumvc歌曲列表控制器是需要我们添加到导航栏的栈里面的。
这个需求在开发音乐App的时候会用到,因为有一个迷你播放器会游离于整个项目,点击底部迷你播放器present整个播放器详情上来,然后有一个回退按键,点击回到歌曲列表。
做电商项目的时候经常遇到这样的一个需求,从首页 -> 商品列表 -> 商品详情 -> 订单详情 -> 付款页面 ,走到这里,导航栏控制器已经添加了多个控制器到栈去里面了,在这个时候如果不进行付款的话,不会按照之前的路径返回的,如果要求我们直接返回到首页里,但是我们并不知道我们跳了多少个控制器,这个时候需要我们通过递归的方式把除了第一控制器(首页)和最后一个控制器(付款成功页),意外的所有页面都删除它。然后再pop回到首页里面。
注意:我们可以在push到最后一个控制器的时候,就是倒数第二个页面,删除控制器,也可以在最后一个页面点击pop回来之前删除控制器。下面OC得代码是倒数第二个控制器push之后删除控制器的,swift的代码是pop的时候才删除控制器。
OC-递归删除控制器-pop返回控制器
在最后一个页面新建一个存储导航栏数组
@property (nonatomic,strong) NSMutableArray<UIViewController *> *muArr;
点击按键的方法
#pragma mark - 支付宝 支付成功后的处理
-(void)paySuccessDispose{
[self.navigationController pushViewController:orderVC animated:YES];
//使用递归删除多余的控制器
self.muArr = [NSMutableArray arrayWithArray:self.navigationController.viewControllers];
[self removeVC];
}
递归删除控制器的方法
//删除多余的控制器
-(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];
}
Swift-递归删除控制器-pop返回控制器
在最后一个页面新建一个存储导航栏数组
var muArr = [UIViewController]()
点击按键的方法
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)
}
递归删除控制器的方法
//删除多余的控制器
func removeVC() {
if muArr.count > 2 {
muArr.remove(at: muArr.count - 2)
} else {
self.navigationController?.setViewControllers(muArr, animated: false)
return
}
removeVC()
}