[iOS开发]present和push

39 篇文章 0 订阅

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值