iOS开发基础65-iPad 开发指南:设备特性、Modal 呈现、Size Classes 与 iPadOS 多任务

iPad 开发深度解析:设备特性、Modal 呈现、Size Classes 与 iPadOS 多任务

本文系统梳理 iPad 开发:iPad 与 iPhone 的区别、屏幕尺寸与分辨率、特有 API 的历史变迁与现代替代、Modal 呈现样式与过渡样式、横竖屏判断的正确方式、以及现代 iPad 开发的核心——Size Classes 与 Universal App 适配、iPadOS 多任务(Slide Over/Split View/画中画)。


一、iPad 简介

1. 什么是 iPad

iPad 是苹果公司于 2010 年发布的平板电脑,定位介于 iPhone 和笔记本电脑之间。与 iPhone 一样搭载 iOS 操作系统,2019 年起 iPad 专属系统更名为 iPadOS,增加了多任务、文件管理、鼠标支持等 iPad 专属能力。

2. iPhone 和 iPad 的区别

对比项 iPhone iPad
屏幕尺寸 小(4.7~6.9 英寸) 大(7.9~12.9 英寸)
UI 排布 紧凑,单列为主 宽松,可多列/分栏
虚拟键盘 无退出键 有退出键盘(dismiss)键
屏幕方向 一般 3 个方向(Plus/Max 支持 4 个) 4 个方向(官方建议全方向支持)
系统 iOS iPadOS(2019+)
多任务 有限 丰富(Slide Over、Split View、画中画)
  • UIPopoverController:iOS 8 已废弃,被通用的 UIPopoverPresentationController 替代(iPhone 和 iPad 都可用,iPhone 上默认弹出为全屏 Sheet,可配置为 Popover)。
  • UISplitViewController:iOS 8+ 已通用,iPhone 上也可使用(在 iPhone 上主视图和详情视图不会同时显示,而是 push 导航)。
  • UIActionSheet:iOS 8 已废弃,被 UIAlertController(style 为 UIAlertControllerStyleActionSheet)替代,跨设备通用。

3. 屏幕尺寸和分辨率

以下为逻辑点(pt,Point),不是物理像素。iOS 开发中布局用逻辑点,系统自动转换为像素(@1x/@2x/@3x)。

iPhone 常见逻辑分辨率:

机型 英寸 逻辑分辨率(pt)
iPhone 4s 3.5 320 × 480
iPhone 5/5s/SE 4.0 320 × 568
iPhone 6/7/8/SE2 4.7 375 × 667
iPhone 6/7/8 Plus 5.5 414 × 736
iPhone X/XS/11 Pro 5.8 375 × 812
iPhone XR/11 6.1 414 × 896
iPhone XS Max/11 Pro Max 6.5 414 × 896
iPhone 12/13/14 Pro 6.1 390 × 844
iPhone 12/13/14 Pro Max 6.7 428 × 926

iPad 常见逻辑分辨率:

机型 英寸 逻辑分辨率(pt)
iPad 2/3/4/Air 9.7 768 × 1024
iPad mini 1/2/3/4/5 7.9 768 × 1024
iPad Pro(第一代/第二代) 12.9 1024 × 1366
iPad Pro 10.5 / Air 3 10.5 834 × 1112
iPad 7/8/9 10.2 810 × 1080
iPad Pro 11(1/2/3/4代) 11 834 × 1194
iPad Pro 12.9(3/4/5/6代) 12.9 1024 × 1366
iPad mini 6 8.3 744 × 1133
iPad 10 10.9 820 × 1180
iPad Air 4/5 10.9 820 × 1180

iPad 屏幕尺寸多样,不要硬编码 1024/768 来判断横竖屏,应使用 width > height 或 Size Classes。

4. 设备支持总结

  • iPhone:只能运行 iPhone 应用。
  • iPad:可以运行 iPad 应用和 iPhone 应用(iPhone 应用在 iPad 上以 1x/2x 放大模式运行,或"缩放"模式全屏显示)。
  • 开发流程:iPhone 和 iPad 开发流程一致,iPhone 开发知识同样适用于 iPad。现代开发推荐 Universal App(一个 App 同时适配 iPhone 和 iPad)。

二、iPad 开发的 Modal

1. 简介

在 iPhone 上,Modal 通常从屏幕底部弹出并覆盖整个屏幕。在 iPad 上,Modal 使用频率更高,且有更多特有的呈现样式(如 PageSheet、FormSheet、Popover)。

2. 呈现样式(ModalPresentationStyle)

样式 效果 说明
UIModalPresentationFullScreen 全屏显示 传统默认样式
UIModalPresentationPageSheet 宽度为竖屏宽度,高度为屏幕高 iPad 特有,左右留边
UIModalPresentationFormSheet 屏幕中间一小块区域 iPad 特有,居中弹窗
UIModalPresentationCurrentContext 跟随父控制器的呈现样式 用于嵌套 modal
UIModalPresentationOverFullScreen 全屏,底层视图不移除 半透明背景常用
UIModalPresentationOverCurrentContext 当前上下文上覆盖,底层不移除 半透明背景常用
UIModalPresentationPopover 弹出气泡(锚定到某个视图/按钮) iOS 8+ 通用,iPad 原生,iPhone 需配置
UIModalPresentationAutomatic 系统自动选择最佳样式 iOS 13+ 默认
// 设置 Modal 呈现样式
UIViewController *modalVC = [[UIViewController alloc] init];
modalVC.modalPresentationStyle = UIModalPresentationFormSheet; // iPad 居中弹窗
[self presentViewController:modalVC animated:YES completion:nil];

iOS 13+ 变化:默认 modalPresentationStyleUIModalPresentationAutomatic。在 iPhone 上表现为页面 Sheet(非全屏,下拉可关闭);在 iPad 上根据内容自动选择 FormSheet 或 Popover。如果需要强制全屏,需显式设置 UIModalPresentationFullScreen

3. 过渡样式(ModalTransitionStyle)

样式 效果 说明
UIModalTransitionStyleCoverVertical 从底部往上弹出 默认
UIModalTransitionStyleFlipHorizontal 三维翻转 正面翻到背面
UIModalTransitionStyleCrossDissolve 淡入淡出 透明度渐变
UIModalTransitionStylePartialCurl 翻页效果 必须配合 FullScreen 呈现样式
modalVC.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;

iOS 13+ 还支持自定义转场动画(UIViewControllerAnimatedTransitioning)和交互式转场。

4. Popover 弹出(现代通用方案)

iOS 8+ 用 UIPopoverPresentationController 实现弹出气泡,替代已废弃的 UIPopoverController,iPhone 和 iPad 通用:

- (IBAction)showPopover:(UIButton *)sender {
    UIViewController *contentVC = [[UIViewController alloc] init];
    contentVC.modalPresentationStyle = UIModalPresentationPopover;
    contentVC.preferredContentSize = CGSizeMake(200, 300);
    
    // 配置 Popover
    UIPopoverPresentationController *popover = contentVC.popoverPresentationController;
    popover.sourceView = sender;
    popover.sourceRect = sender.bounds;
    popover.permittedArrowDirections = UIPopoverArrowDirectionAny;
    popover.delegate = self; // 可通过 delegate 让 iPhone 也显示为 Popover
    
    [self presentViewController:contentVC animated:YES completion:nil];
}

// 通过此代理方法让 Popover 在 iPhone 上也以气泡形式显示(默认 iPhone 上会转为全屏 Sheet)
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller {
    return UIModalPresentationNone; // 返回 None 表示不适应,保持 Popover 样式
}

三、开发中的注意点

1. 判断横竖屏幕(正确方式)

self.view.bounds.size.width == 1024 判断横屏,不推荐

  • 硬编码 1024 不通用(不同 iPad 尺寸横屏宽度不同,如 11寸 Pro 横屏宽 1194,12.9寸 宽 1366)。
  • viewDidLoadbounds 可能还未完成布局,尺寸不准确。

正确方式:

// 方式一:比较宽高(最通用,推荐)
- (BOOL)isLandscape {
    return self.view.bounds.size.width > self.view.bounds.size.height;
}

// 方式二:通过 UIDevice
- (BOOL)isLandscapeByDevice {
    UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
    return UIDeviceOrientationIsLandscape(orientation);
}

// 方式三:通过状态栏方向(iOS 13+ 逐渐废弃)
- (BOOL)isLandscapeByStatusBar {
    UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
    return UIInterfaceOrientationIsLandscape(orientation);
}

推荐用方式一(比较宽高),最稳定且不依赖设备方向传感器。

2. 屏幕旋转回调

iOS 8+ 推荐用 viewWillTransitionToSize:withTransitionCoordinator: 监听尺寸变化(替代旧的 willRotateToInterfaceOrientation: 等方法):

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
    
    // 用 width > height 判断,不硬编码 1024
    BOOL isLandscape = size.width > size.height;
    NSLog(@"即将旋转到: %@", isLandscape ? @"横屏" : @"竖屏");
    
    // 在转场动画中更新布局
    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
        // 旋转过程中更新 UI(如重新布局、更新约束)
        if (isLandscape) {
            // 横屏布局
        } else {
            // 竖屏布局
        }
    } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
        // 旋转完成
    }];
}

3. 状态栏设置

- (UIStatusBarStyle)preferredStatusBarStyle {
    return UIStatusBarStyleLightContent; // 白色状态栏
    // 或 UIStatusBarStyleDarkContent(iOS 13+,黑色状态栏)
}

// 状态栏是否隐藏
- (BOOL)prefersStatusBarHidden {
    return NO;
}

iOS 13+ 状态栏样式受 UINavigationController 和 Modal 呈现样式影响,可能需要在导航控制器中重写 childViewControllerForStatusBarStyle

4. 屏幕方向支持配置

在 Info.plist 中配置支持的方向:

<!-- iPad 支持全部 4 个方向 -->
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
    <string>UIInterfaceOrientationPortrait</string>
    <string>UIInterfaceOrientationPortraitUpsideDown</string>
    <string>UIInterfaceOrientationLandscapeLeft</string>
    <string>UIInterfaceOrientationLandscapeRight</string>
</array>

<!-- iPhone 一般支持 3 个方向(不含倒竖屏) -->
<key>UISupportedInterfaceOrientations</key>
<array>
    <string>UIInterfaceOrientationPortrait</string>
    <string>UIInterfaceOrientationLandscapeLeft</string>
    <string>UIInterfaceOrientationLandscapeRight</string>
</array>

也可在代码中控制单个控制器的方向:

// 支持的方向
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskAll; // 全部方向
    // 或 UIInterfaceOrientationMaskLandscape(仅横屏)
}

// 是否允许自动旋转
- (BOOL)shouldAutorotate {
    return YES;
}

四、现代 iPad 开发核心:Size Classes 与 Universal App

1. 为什么需要 Size Classes

iPad 屏幕尺寸多样(7.9~12.9 英寸),且支持分屏多任务(App 可用宽度动态变化),用具体尺寸判断布局不可靠。苹果从 iOS 8 引入 Size Classes(尺寸类),用抽象的 Compact(紧凑)和 Regular(常规)描述水平和垂直方向的尺寸,统一适配所有设备和分屏状态。

2. Size Classes 对应关系

设备 状态 水平(Horizontal) 垂直(Vertical)
iPhone 竖屏 Compact Regular
iPhone 横屏(除 Plus/Max) Compact Compact
iPhone Plus/Max 横屏 Regular Compact
iPad 全屏(横竖屏) Regular Regular
iPad Split View 1/3 Compact Regular
iPad Split View 1/2 Regular Regular
iPad Slide Over Compact Regular

3. 使用 Size Classes

代码中获取当前 Size Classes:

- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
    [super traitCollectionDidChange:previousTraitCollection];
    
    // 水平方向尺寸类
    UIUserInterfaceSizeClass horizontal = self.traitCollection.horizontalSizeClass;
    // 垂直方向尺寸类
    UIUserInterfaceSizeClass vertical = self.traitCollection.verticalSizeClass;
    
    if (horizontal == UIUserInterfaceSizeClassRegular) {
        NSLog(@"水平方向常规(iPad 全屏或宽分屏),显示多列布局");
    } else {
        NSLog(@"水平方向紧凑(iPhone 或窄分屏),显示单列布局");
    }
}

Storyboard/XIB 中使用 Size Classes:

在 Interface Builder 底部选择 Size Classes(如 wAny hAnywCompact hRegular),可为不同尺寸类设置不同的约束、字体、颜色、是否隐藏等。

4. Universal App

Universal App(通用应用)指一个 App 同时适配 iPhone 和 iPad,用同一个 target 和 Bundle ID,通过 Size Classes 和 Auto Layout 自动适配不同设备。这是现代 iOS 开发的推荐方式,替代过去分别维护 iPhone 版和 iPad 版两个 target。

创建 Universal App:Xcode 新建项目时 Devices 选择 Universal


五、iPadOS 多任务与新特性

1. 多任务模式

iPadOS 支持三种多任务模式:

模式 说明
Slide Over(滑动悬停) 一个 App 悬浮在另一个 App 上方,可左右滑动切换
Split View(分屏浏览) 两个 App 并排显示,可调整比例(1/2、1/3、2/3)
画中画(PiP) 视频以小窗口悬浮在其他 App 之上

App 需要在 Info.plist 中声明支持多任务(UIRequiresFullScreen = NO,默认即支持),并通过 Size Classes 适配不同宽度。

2. 其他 iPadOS 特性

  • 鼠标和触控板支持:iPadOS 13+ 支持鼠标/触控板,需适配 UIHoverGestureRecognizer(悬停手势)和指针效果(UIPointerInteraction)。
  • Apple Pencil:支持 UIPencilInteraction、低延迟绘图(PKCanvasView,PencilKit 框架)。
  • 键盘快捷键UIKeyCommand 支持外接键盘快捷键。
  • 文件应用集成:通过 UIDocumentBrowserViewController 集成文件系统。
  • 拖放(Drag and Drop)UIDragInteraction / UIDropInteraction,支持跨 App 拖放。

六、Swift 版本对照

判断横竖屏(Swift)

var isLandscape: Bool {
    view.bounds.width > view.bounds.height
}

屏幕旋转回调(Swift)

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)
    let isLandscape = size.width > size.height
    coordinator.animate { _ in
        // 旋转中更新布局
    } completion: { _ in
        // 旋转完成
    }
}

Size Classes(Swift)

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
    switch traitCollection.horizontalSizeClass {
    case .regular:
        print("水平常规,多列布局")
    case .compact:
        print("水平紧凑,单列布局")
    case .unspecified:
        break
    @unknown default:
        break
    }
}
let modalVC = UIViewController()
modalVC.modalPresentationStyle = .formSheet
modalVC.modalTransitionStyle = .crossDissolve
present(modalVC, animated: true)

Popover(Swift)

@IBAction func showPopover(_ sender: UIButton) {
    let contentVC = UIViewController()
    contentVC.modalPresentationStyle = .popover
    contentVC.preferredContentSize = CGSize(width: 200, height: 300)
    if let popover = contentVC.popoverPresentationController {
        popover.sourceView = sender
        popover.sourceRect = sender.bounds
        popover.permittedArrowDirections = .any
        popover.delegate = self
    }
    present(contentVC, animated: true)
}

extension ViewController: UIPopoverPresentationControllerDelegate {
    func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
        return .none // iPhone 上也保持 Popover 样式
    }
}

七、总结

  • iPad 简介:2010 年发布,2019+ 系统更名 iPadOS;屏幕更大、UI 更宽松、键盘有退出键、支持 4 方向、多任务丰富;iPhone 应用可在 iPad 上放大运行;推荐 Universal App 一套代码适配双设备。
  • 过时 API 修正:UIPopoverController(iOS 8 废弃)→ UIPopoverPresentationController(通用);UIActionSheet(iOS 8 废弃)→ UIAlertController(ActionSheet 样式);UISplitViewController iOS 8+ 已通用(iPhone 也可用)。
  • 屏幕尺寸:布局用逻辑点(pt)非像素;iPad 尺寸多样(768x1024 ~ 1024x1366),不要硬编码 1024。
  • Modal 呈现样式:FullScreen/PageSheet/FormSheet/CurrentContext/OverFullScreen/OverCurrentContext/Popover/Automatic;iOS 13+ 默认 Automatic(iPhone 页面 Sheet,iPad 自动选 FormSheet/Popover),强制全屏需显式设 FullScreen;过渡样式 CoverVertical/FlipHorizontal/CrossDissolve/PartialCurl(需 FullScreen)。
  • 横竖屏判断:不要硬编码 width == 1024,推荐用 width > height 比较;旋转回调 viewWillTransitionToSize:withTransitionCoordinator:(iOS 8+),在 coordinator.animateAlongsideTransition 中更新布局。
  • Size Classes(现代核心):iOS 8+ 用 Compact/Regular 抽象水平和垂直尺寸,统一适配所有设备和分屏状态;traitCollectionDidChange: 监听变化;Storyboard 可按尺寸类设置不同约束。
  • iPadOS 多任务:Slide Over(悬浮)、Split View(分屏 1/2、1/3、2/3)、画中画 PiP;App 默认支持(UIRequiresFullScreen=NO),需用 Size Classes 适配动态宽度。
  • iPadOS 新特性:鼠标/触控板(UIHoverGestureRecognizer/UIPointerInteraction)、Apple Pencil(PencilKit)、键盘快捷键(UIKeyCommand)、文件集成(UIDocumentBrowserViewController)、跨 App 拖放(UIDragInteraction/UIDropInteraction)。

posted @ 2015-10-12 19:47  Mr.陳  阅读(1578)  评论(0)    收藏  举报