在开发过程中,我们有时会遇到界面切换问题,有两种基本的方式可以实现界面切换:
push
方法,将界面从右侧推进来,借助的是导航控制器,在新界面会有导航控制器,并且左上角会自动生成一个导航栏按钮可以返回上一层级,当然要想自定义返回按钮就得在按钮的点击事件中借助pop
方法present
方法,将页面从下侧切进来,返回上一层级则需要dismiss
方法
push和present相同点
push和present都可以推出新的界面
- push与pop对应
先在window上加一个navigation,然后以VCRoot作为navigation的根视图进行导航
UIWindowScene* windowScene = (UIWindowScene *)scene;
self.window = [[UIWindow alloc] initWithWindowScene: windowScene];
self.window.frame = windowScene.coordinateSpace.bounds;
//将window根视图设置成navigation
UINavigationController* navigation = [[UINavigationController alloc] initWithRootViewController: [[VCRoot alloc] init] ];
self.window.rootViewController = navigation;
[self.window makeKeyAndVisible];
接下来在VCRoot界面使用push和pop切换其他界面
//创建新的视图控制器
NewViewController* newViewController = [[newViewController alloc] init];
//推出新的视图
[self.navigationController pushViewController: newViewController animated: YES];
//返回上一层级
[self.navigationController popViewControllerAnimated: YES];
//返回根视图
[self.navigationController popToRootViewControllerAnimated: YES];
//返回指定视图
[self.navigationController popToViewController: newViewController animated: YES];
//返回指定级数,此处为第一层级
[self.navigationController popToViewController: [self.navigationController.viewControllers objectAtIndex: 0 ] animated: YES];
- present与dismiss对应
//创建新的视图
NewViewController* newViewController = [[newViewController alloc] init];
//推出新的视图
[self presentViewController: newViewOCntroller animated: YES completion: nil];
//返回上一层级
[self dismissViewControllerAnimated: YES completion: nil];
现在新版本的present并没有将新视图显示完全,因此可以拖拽新视图返回上一层级
要想将present来的视图显示完全,占满整个屏幕,可以使用以下代码:
newViewController.modalPresentationStyle = UIModalPresentationFullScreen;
present和pop不同点
从上面的代码我们可以看出,push可以返回指定层级的视图,而present不可以,只能逐级返回,这是因为push的所有视图由视图栈控制
我们可以回想一下平时用的App,是不是不同业务界面的切换用的都是present,同一业务不同界面之间的切换用的都是push
以下是几个在写项目过程中遇到的问题
导航控制器消失🫠
如果在导航之间有了一个present
之后,你会发现当前页面的navigationController是空的,也就是说导航控制器不管用了
解决办法是获取当前的window
实例,在得到window的根视图,即为导航器,然后根据导航器的索引就可以找到当前的视图
// 先取消原来的控制器
[self dismissViewControllerAnimated:NO completion:nil];
ViewController *VC=[[ViewController alloc]init];
UIWindow *window=[[UIApplication sharedApplication]keyWindow];
UINavigationController *nav0=(UINavigationController *)window.rootViewController;
UIViewController *viewController=[nav0.viewControllers objectAtIndex:1];
[viewController.navigationController pushViewController:VC animated:YES];
判断当前viewcontroller是push还是present的方式显示的
NSArray *viewcontrollers=self.navigationController.viewControllers;
if (viewcontrollers.count>1) {
if ([viewcontrollers objectAtIndex:viewcontrollers.count-1]==self) {
//push方式
[self.navigationController popViewControllerAnimated:YES];
}
}
else{
//present方式
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
通过present
的方式显示的viewController不会存入self.navigationController.viewControllers
数组中
而通过push
方式显示的viewcController会存在该数组的最后
隐藏push界面的返回键
要隐藏push来的界面自动生成的返回键,只需以下一句代码:
self.navigationItem.hidesBackButton=YES;