iOS开发基础31-Modal 与 Push 详解
在 iOS 开发中,视图控制器(View Controller)的转场方式可以大致分为两类:模态(Modal)和导航推送(Push)。这两种方法有各自的适用场景、优点和缺点。
一、Push 转场
概述
Push 转场是一种基于导航控制器(UINavigationController)的视图控制器切换方式。当你使用 Push 转场时,当前视图控制器将被推入导航栈,新的视图控制器显示在屏幕上。同时,导航控制器会自动提供返回按钮以便用户返回到前一个视图控制器。
适用场景
- 层级结构:通常使用 Push 转场来实现具有层次结构的视图控制,如文件夹层级、设置页面等。
- 导航:适用于需要导航和返回的场景。
基本用法
初始化 UINavigationController
首先,需要初始化一个导航控制器并设置其根视图控制器:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
// 初始化根视图控制器
UIViewController *rootViewController = [[UIViewController alloc] init];
rootViewController.view.backgroundColor = [UIColor whiteColor];
rootViewController.title = @"Root";
// 初始化导航控制器
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
return YES;
}
使用 Push 转场推入新视图控制器
在某个视图控制器中,通过调用 pushViewController:animated:
方法来进行 Push 转场:
- (void)navigateToNextViewController {
UIViewController *nextViewController = [[UIViewController alloc] init];
nextViewController.view.backgroundColor = [UIColor lightGrayColor];
nextViewController.title = @"Next";
[self.navigationController pushViewController:nextViewController animated:YES];
}
返回上一个视图控制器
默认情况下,导航控制器会提供一个返回按钮,但你也可以手动调用 popViewControllerAnimated:
方法:
[self.navigationController popViewControllerAnimated:YES];
二、Modal 转场
概述
Modal 转场是一种模态展示视图控制器的方式。在这种转场方式下,新的视图控制器以模态的方式覆盖当前视图控制器,与 Push 不同的是,Modal 转场不会将视图控制器加入到导航栈中。
适用场景
- 独立任务:适用于需要用户完成独立任务的场景,如登录、设置等。
- 弹出视图:适用于需要临时展示的视图控制器,如弹出框。
基本用法
模态展示视图控制器
通过调用 presentViewController:animated:completion:
方法展示一个新的视图控制器:
- (void)presentModalViewController {
UIViewController *modalViewController = [[UIViewController alloc] init];
modalViewController.view.backgroundColor = [UIColor lightGrayColor];
modalViewController.modalPresentationStyle = UIModalPresentationFullScreen; // 全屏展示
[self presentViewController:modalViewController animated:YES completion:nil];
}
模态关闭视图控制器
通过调用 dismissViewControllerAnimated:completion:
方法关闭模态展示的视图控制器:
[self dismissViewControllerAnimated:YES completion:nil];
自定义模态转场样式
iOS 提供了多种模态展示样式,例如 .pageSheet
、.formSheet
等,可以通过设置 modalPresentationStyle
属性来改变展示样式:
- (void)presentCustomModalViewController {
UIViewController *customModalViewController = [[UIViewController alloc] init];
customModalViewController.view.backgroundColor = [UIColor lightGrayColor];
customModalViewController.modalPresentationStyle = UIModalPresentationPageSheet; // 页面样式
[self presentViewController:customModalViewController animated:YES completion:nil];
}
三、Push 与 Modal 的对比
特性 | Push 转场 | Modal 转场 |
---|---|---|
导航控制器 | 需要 | 不需要 |
层级结构 | 适合 | 不适合 |
返回逻辑 | 自动提供返回按钮 | 需要手动实现 |
使用场景 | 文件夹层级、设置 | 登录、设置、弹出框 |
动画效果 | 可自定义 | 可自定义 |
UINavigationController 栈 | 会加入 | 不会加入 |
四、示例代码
以下示例展示了使用 Push 和 Modal 转场的综合实现:
#import "AppDelegate.h"
#import "RootViewController.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
// 初始化根视图控制器并嵌入导航控制器
RootViewController *rootViewController = [[RootViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
return YES;
}
@end
// RootViewController.m 文件
#import "RootViewController.h"
#import "NextViewController.h"
@interface RootViewController ()
@end
@implementation RootViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.title = @"Root";
UIButton *pushButton = [UIButton buttonWithType:UIButtonTypeSystem];
[pushButton setTitle:@"Push ViewController" forState:UIControlStateNormal];
[pushButton addTarget:self action:@selector(pushButtonTapped) forControlEvents:UIControlEventTouchUpInside];
pushButton.frame = CGRectMake(100, 100, 200, 50);
[self.view addSubview:pushButton];
UIButton *modalButton = [UIButton buttonWithType:UIButtonTypeSystem];
[modalButton setTitle:@"Present Modal ViewController" forState:UIControlStateNormal];
[modalButton addTarget:self action:@selector(modalButtonTapped) forControlEvents:UIControlEventTouchUpInside];
modalButton.frame = CGRectMake(100, 200, 200, 50);
[self.view addSubview:modalButton];
}
- (void)pushButtonTapped {
NextViewController *nextViewController = [[NextViewController alloc] init];
[self.navigationController pushViewController:nextViewController animated:YES];
}
- (void)modalButtonTapped {
NextViewController *modalViewController = [[NextViewController alloc] init];
modalViewController.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentViewController:modalViewController animated:YES completion:nil];
}
@end
// NextViewController.m 文件
#import "NextViewController.h"
@interface NextViewController ()
@end
@implementation NextViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor lightGrayColor];
self.title = @"Next";
if (self.presentingViewController) {
UIButton *closeButton = [UIButton buttonWithType:UIButtonTypeSystem];
[closeButton setTitle:@"Close" forState:UIControlStateNormal];
[closeButton addTarget:self action:@selector(closeButtonTapped) forControlEvents:UIControlEventTouchUpInside];
closeButton.frame = CGRectMake(100, 100, 100, 50);
[self.view addSubview:closeButton];
}
}
- (void)closeButtonTapped {
[self dismissViewControllerAnimated:YES completion:nil];
}
@end
五、总结
在 iOS 开发中,Push 和 Modal 是两种常见的视图控制器转场方式,各有优缺点。Push 转场适用于需要层级导航的场景,而 Modal 转场适用于需要临时展示或者完成独立任务的场景。通过深入理解和灵活应用这两种转场方式,可以显著提高 iOS 应用的用户体验和界面效果。