一、背景简介
有时候我们会需要在一个视图上modal出两层,意思是第一个视图控制器modal出第二个视图控制器,再在第二个视图控制器上modal出第三个视图控制器,但是会有一个需求就是在第三个视图控制器上响应一个时间直接调回到第一个视图控制器。
二、问题解决
我们可以在第三个控制器上拿到它的presentingController也就是上一个控制器
贴代码:
ViewController.m的源码如下:
#import "ViewController.h"
#import "ModalFirstController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
ModalFirstController *mfVc = [[ModalFirstController alloc]init];
[self presentViewController:mfVc animated:YES completion:nil];
}
@end
ModalFirstController.h的源码如下:
#import <UIKit/UIKit.h>
@interface ModalFirstController : UIViewController
@end
ModalFirstController.m的源码如下:
#import "ModalFirstController.h"
#import "ModalSecondController.h"
@interface ModalFirstController ()
@end
@implementation ModalFirstController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor redColor];
[self setBackItem];
}
- (void)setBackItem{
UIButton *btn = [[UIButton alloc]init];
btn.frame = CGRectMake(0, 0, 100, 50);
btn.center = self.view.center;
btn.backgroundColor = [UIColor purpleColor];
[btn setTitle:@"点我返回" forState:UIControlStateNormal];
[self.view addSubview:btn];
[btn addTarget:self action:@selector(goBack) forControlEvents:UIControlEventTouchUpInside];
}
- (void)goBack{
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
ModalSecondController *msVc = [[ModalSecondController alloc]init];
[self presentViewController:msVc animated:YES completion:nil];
}
@end
ModalSecondController.h源码如下:
#import <UIKit/UIKit.h>
@interface ModalSecondController : UIViewController
@end
ModalSecondController.m源码如下:
#import "ModalSecondController.h"
@interface ModalSecondController ()
@end
@implementation ModalSecondController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor orangeColor];
[self setBackItem];
}
- (void)setBackItem{
UIButton *btn = [[UIButton alloc]init];
btn.frame = CGRectMake(0, 0, 100, 50);
btn.center = self.view.center;
btn.backgroundColor = [UIColor purpleColor];
[btn setTitle:@"点我返回" forState:UIControlStateNormal];
[self.view addSubview:btn];
[btn addTarget:self action:@selector(goBack) forControlEvents:UIControlEventTouchUpInside];
}
- (void)goBack{
//以下两种方式的实现效果一样
UIViewController *vc = self.presentingViewController;
[self dismissViewControllerAnimated:NO completion:^{
[vc dismissViewControllerAnimated:YES completion:nil];
}];
//[self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}
首先创建一个工程,在ViewController上的touchesBegan上modal出ModalFirstController控制器,然后在ModalFirstController上的touchesBegan上接着modal出ModalSecondController控制器.
我们在ModalSecondController.m文件中添加了一个按钮,按钮的功能是直接能够返回到ViewController上,我们的做法是找到ModalSecondController的presentingViewController控制器,也就是ModalFirstController控制器,先由ModalSecondController控制器dismiss,然后再在completion代码块中用ModalSecondController的presentingViewController控制器dismiss掉就可以了,具体代码见ModalSecondController.m源码中go back方法,代码如下:
- (void)goBack{
//以下两种方式的实现效果一样
UIViewController *vc = self.presentingViewController;
[self dismissViewControllerAnimated:NO completion:^{
[vc dismissViewControllerAnimated:YES completion:nil];
}];
}
三、文末总结
其实我们可以多利用一下系统提供的接口来实现我们的需求,另外还有一些需求,比如说我们需要在自定义视图上push或者modal出一个控制器,那这个又到底怎么做呢?
方式一:用响应链
方式二:用属性,但是一定要注意循环引用的问题
方式三:通过keyWindow然后一层层来逻辑判断最终拿到当前的控制器
具体的每一种方式的代码我后面有时间给以给大家写一个,有问题还希望各位看官能够及时指出。