[iOS开发]present和push
Posted Billy Miracle
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[iOS开发]present和push相关的知识,希望对你有一定的参考价值。
present和push:
- push与present都可以推出新的界面。
- present与dismiss对应,push和pop对应。
- present只能逐级返回。
- push在内存中是以压栈的方式,跳转到摸个控制器,跳转后控制器都存放在Navigation中的ViewControllers数组中。可以返回上一级,也可以返回到根ViewController,其他ViewController。
假设从A控制器通过present的方式跳转到了B控制器,那么
A.presentedViewController
就是B控制器,
B.presentingViewController
就是A控制器。
下面我们会使用程序观察体会。
第一个ViewController中:
- (void)present {
SecondViewController *secondViewController = [[SecondViewController alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:secondViewController];
nav.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentViewController:nav animated:YES completion:nil];
NSLog(@"%p\\n%p", self, self.presentedViewController);
}
第二个ViewController中:
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"%p\\n%p", self.navigationController, self.presentingViewController);
...
...
}
运行结果:
点击并present出第二个视图控制器后输出:
0x12dd07ba0
0x13280a400
0x13280a400
0x12dd07ba0
可以看到A的presentedViewController和B一样,B的presentingViewController和A一样。
上面说过,present对应dismiss,第二个ViewController中的返回事件:
- (void)pressBack {
[self dismissViewControllerAnimated:YES completion:nil];
}
示例程序的FirstViewController通过present的方式显示以SecondViewController为根视图的navigationController。再之后,Second、Third、Fourth之间的切换都是push和pop。
在Second及以后的视图中试图使用dismissViewController方法,都会回到FirstViewController,比如,第三个页面的backToFirstButton的点击事件为:
- (void)pressToFirst {
[self dismissViewControllerAnimated:YES completion:nil];
}
这样,点击了按钮后会直接返回第一页面。
前面提到,popViewController方法可以返回上一页,如果要返回得层数更多,可以使用传值方法,将信息传回上一页,再pop一次,示例:
第四页面:
//.h
@protocol FourthBackToSecondDelegate <NSObject>
- (void)backToSecond;
@end
@interface FourthViewController : UIViewController
@property (nonatomic, assign) id<FourthBackToSecondDelegate> delegate;
@end
//.m中返回第二界面的事件
- (void)pressToSecond {
[self.navigationController popViewControllerAnimated:NO];
[self.delegate backToSecond];
}
第三个界面:
//.m实现代理函数
- (void)backToSecond {
[self.navigationController popViewControllerAnimated:YES];
}
这样以来,就可以返回两级页面了,但是十分麻烦,不美观,前面还说过,跳转后控制器都存放在Navigation中的ViewControllers数组中,那么我们是否可以根据这个数组来实现一些操作呢?先打印一下数组看看内容:
//ForthViewController.m中
NSLog(@"%@", self.navigationController.viewControllers);
结果:
(
"<SecondViewController: 0x15b704710>",
"<ThirdViewController: 0x159d11d80>",
"<FourthViewController: 0x15d805870>"
)
可以看到,数组里面果然存放着三个ViewController。这样一来,就可以使用popToRootViewControllerAnimated:
或者popToViewController: animated:
函数来控制pop到的页面了:
- (void)pressToSecond {
// [self.navigationController popViewControllerAnimated:NO];
// [self.delegate backToSecond];
// [self.navigationController popToRootViewControllerAnimated:YES];
[self.navigationController popToViewController:self.navigationController.viewControllers[0] animated:YES];
}
这三种结果一样,返回SecondViewController,但使用下面两个自带的函数的动画过渡效果更好,而且代码简单。
下面附上四个Controller.m的代码:
// ViewController.m
// PresentAndPush
#import "ViewController.h"
#import "SecondViewController.h"
#import "View.h"
@interface ViewController ()
@property (nonatomic, strong) View *firstView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_firstView = [[View alloc] initWithFrame:self.view.frame];
[_firstView.pushButton addTarget:self action:@selector(present) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_firstView];
}
- (void)present {
SecondViewController *secondViewController = [[SecondViewController alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:secondViewController];
nav.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentViewController:nav animated:YES completion:nil];
NSLog(@"%p\\n%p", self, self.presentedViewController);
}
@end
// SecondViewController.m
// PresentAndPush
#import "SecondViewController.h"
#import "SecondView.h"
#import "ThirdViewController.h"
@interface SecondViewController ()
@property (nonatomic, strong) SecondView *secondView;
@end
@implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"%p\\n%p", self.navigationController, self.presentingViewController);
_secondView = [[SecondView alloc] initWithFrame:self.view.frame];
[self.view addSubview:_secondView];
[_secondView.backButton addTarget:self action:@selector(pressBack) forControlEvents:UIControlEventTouchUpInside];
[_secondView.pushButton addTarget:self action:@selector(pressPush) forControlEvents:UIControlEventTouchUpInside];
}
- (void)pressBack {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)pressPush {
ThirdViewController *thirdViewController = [[ThirdViewController alloc] init];
[self.navigationController pushViewController:thirdViewController animated:YES];
}
@end
// ThirdViewController.m
// PresentAndPush
#import "ThirdViewController.h"
#import "ThirdView.h"
#import "FourthViewController.h"
@interface ThirdViewController ()<FourthBackToSecondDelegate>
@property (nonatomic, strong) ThirdView *thirdView;
@end
@implementation ThirdViewController
- (void)viewDidLoad {
[super viewDidLoad];
_thirdView = [[ThirdView alloc] initWithFrame:self.view.frame];
[self.view addSubview:_thirdView];
[_thirdView.pushButton addTarget:self action:@selector(pressPush) forControlEvents:UIControlEventTouchUpInside];
[_thirdView.backButton addTarget:self action:@selector(pressBack) forControlEvents:UIControlEventTouchUpInside];
[_thirdView.backToFirstButton addTarget:self action:@selector(pressToFirst) forControlEvents:UIControlEventTouchUpInside];
}
- (void)pressPush {
FourthViewController *fourthViewController = [[FourthViewController alloc] init];
fourthViewController.delegate = self;
[self.navigationController pushViewController:fourthViewController animated:YES];
}
- (void)pressBack {
[self.navigationController popViewControllerAnimated:YES];
}
- (void)pressToFirst {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)backToSecond {
[self.navigationController popViewControllerAnimated:YES];
}
@end
// FourthViewController.m
// PresentAndPush
#import "FourthViewController.h"
#import "FourthView.h"
@interface FourthViewController ()
@property (nonatomic, strong) FourthView *fourthView;
@end
@implementation FourthViewController
- (void)viewDidLoad {
[super viewDidLoad];
_fourthView = [[FourthView alloc] initWithFrame:self.view.frame];
[self.view addSubview:_fourthView];
[_fourthView.backButton addTarget:self action:@selector(pressBack) forControlEvents:UIControlEventTouchUpInside];
[_fourthView.backToSecondButton addTarget:self action:@selector(pressToSecond) forControlEvents:UIControlEventTouchUpInside];
NSLog(@"%@", self.navigationController.viewControllers);
}
- (void)pressBack {
[self.navigationController popViewControllerAnimated:YES];
}
- (void)pressToSecond {
// [self.navigationController popViewControllerAnimated:NO];
// [self.delegate backToSecond];
// [self.navigationController popToRootViewControllerAnimated:YES];
[self.navigationController popToViewController:self.navigationController.viewControllers[0] animated:YES];
}
@end
完整代码的Demo地址:https://github.com/BillyMiracle/PushAndPresent.git
以上是关于[iOS开发]present和push的主要内容,如果未能解决你的问题,请参考以下文章
iOS Storyboard Presenting Segues "relationship, embed, push, modal, custom" 类型
ios swift 判断uiviewcontroller时push present 进来的 还是pop进来的
push和present 两种方式。viewWillDisAppear,viewDidDisAppear的顺序