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 应用的用户体验和界面效果。

posted @ 2015-08-03 23:47  Mr.陳  阅读(299)  评论(0编辑  收藏  举报