iOS dismissViewController到指定页面或dismiss多层

项目中经常有这样的需求:
A present弹出 B
B present弹出 C
C dismiss回到 A
对数模态弹出的控制器不像push的那样,有系统的导航栏统一管理。为实现这一目的,我仔细研究了官方文档,发现了这么一句话

The presenting view controller is responsible for dismissing the view controller it presented. If you call this method on the presented view controller itself, it automatically forwards the message to the presenting view controller.

也就是说,谁污染谁治理,A present弹出 B,本应该由A dismiss B然后回到再A。
我们一般都是直接用B dismiss,这是因为系统会自动优化,当B视图控制器没有present弹出过其他视图控制器的时候,dismissViewController方法会自动交给B的presentingViewController执行,也就是A视图。

If you present several view controllers in succession, thus building a stack of presented view controllers, calling this method on a view controller lower in the stack dismisses its immediate child view controller and all view controllers above that child on the stack. When this happens, only the top-most view is dismissed in an animated fashion; any intermediate view controllers are simply removed from the stack. The top-most view is dismissed using its modal transition style, which may differ from the styles used by other view controllers lower in the stack.

也就是说,其实在present多个视图控制器的时候,系统也维护了一个栈,以我们现在这个情况为例,从栈底到栈顶依次是A->B->C。当栈中某个位置的视图控制器执行dismissViewController方法的时候,栈中所有在它之上的视图控制器都会被dismiss,不同的是,栈顶的视图控制器将会以动画方式被dismiss,而中间的视图控制器只是简单的remove掉。

所以想要实现直接从C跳转回A也简单,就是直接在A中执行dismissViewController方法,此时B也会自动销毁,同pop方法类似。但是我们需要在每一个弹出的控制器中都设置监听,来实现谁污染谁治理这个规则。这样就太乱了。

好在苹果应该是想到这一点,为我们提供了两个属性,分别是presentingViewController和presentedViewController。
A弹出B 则A是B的presentingViewController,
B是A的presentedViewController。如果B还弹出了C,那么B同时也是C的presentingViewController。

说了这么多,也该上代码了,同上pop一样,我也是写了一个Extension,复制粘贴即可轻松实现dismiss多层。不过呢我没有封装完成后的回调,需要的同学可以自己加上。

.h 文件

@interface UIViewController (Extension)
/**  在主线程执行操作*/
- (void)performSelectorOnMainThread:(void(^)(void))block;

/**  退出 presentViewController  count:次数*/
- (void)dismissViewControllerWithCount:(NSInteger)count animated:(BOOL)animated;


/**  退出 presentViewController 到指定的控制器*/
- (void)dismissToViewControllerWithClassName:(NSString *)className animated:(BOOL)animated;

@end


.m 文件


@implementation UIViewController (Extension)
/**  在主线程执行操作*/
- (void)performSelectorOnMainThread:(void(^)(void))block{
    if ([[NSThread currentThread] isMainThread]) {
        block();
    }else{
        dispatch_sync(dispatch_get_main_queue(), ^{
            block();
        });
    }
}


/**  退出 presentViewController  count:次数*/
- (void)dismissViewControllerWithCount:(NSInteger)count animated:(BOOL)animated{

    count--;
    // 不是自己,并且自己弹出过VC, 递归交给自己弹出的VC处理
    if (count>0 && self.presentingViewController) {
        [self.presentingViewController dismissViewControllerWithCount:count animated:animated];
    }
    else{
        [self dismissViewControllerAnimated:animated completion:nil];
    }
}



/**  退出 presentViewController 到指定的控制器*/
- (void)dismissToViewControllerWithClassName:(NSString *)className animated:(BOOL)animated{

    // 不是自己,并且自己弹出过VC, 递归交给自己弹出的VC处理
    if (![self.class isKindOfClass:NSClassFromString(className)] && self.presentingViewController) {
        [self.presentingViewController dismissToViewControllerWithClassName:className animated:animated];
    }else{
        [self dismissViewControllerAnimated:animated completion:nil];
    }
}

@end




评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值