[Objective-C 与 iOS开发]Xcode16及以上版本创建自动适配iPad和iPhone平台的App的一种办法

Source

1 引言

博主最近在啃一本iOS开发的书,但是这本书是十几年前的了,上面介绍的很多技术与接口都已经过时,有些甚至已经被新版本的iOS所弃用。

其中,书上在介绍到第六章“视图控制器与导航模式”时,提到iPad有两个独占的视图控制器 UISplitViewController 和 UIPopoverViewController(已弃用) 。因此,iPad App 是无法直接复用到 iPhone 平台的,需要进行适配。

早期的Xcode中,可以在创建项目时选择Device,如果选择"Universe",则会创建自动适配 iPhone 和 iPad 的项目模版(包含 iPhone 和 iPad 两个版本的故事版文件,项目启动时根据平台选择使用那哪个文件)。

但是新版本的Xcode在创建项目时却没有这个选项,书上也没有介绍这个自动适配的实现原理。于是博主自己研究了一下,找到了一个可行的实现方式(iOS开发新手,如有错误或有更好的技术实现方式,欢迎评论或私信告诉我)。

2 实现方式

2.1 创建专用故事板

分别为 iPhone 和 iPad 平台创建一个专用的故事板,并根据需要进行编辑。

注意,原本的Main.storyboard不要改名或删除,可以在其中添加一些内容,但是要确保存在 Initial View Controller。

2.2 修改SceneDelegate.m

修改初始化函数,使其根据所在平台选择使用哪个storyboard文件中的根视图为应用窗口的根视图。

- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
    // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
    // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
    // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
    UIViewController *rootViewController;
    
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
        // iPad: 使用SplitViewController
        rootViewController = [self setupiPadInterface];
    } else {
        // iPhone: 使用TabBarController或NavigationController
        rootViewController = [self setupiPhoneInterface];
    }
    
    self.window.rootViewController = rootViewController;
    [self.window makeKeyAndVisible];
}

- (UIViewController *)setupiPadInterface {
    // 从故事板加载iPad专用的SplitViewController
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main_iPad" bundle:nil];
    return [storyboard instantiateInitialViewController];
}

- (UIViewController *)setupiPhoneInterface {
    // 创建iPhone专用的界面(Navigation or TabBar)
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main_iPhone" bundle:nil];
    UINavigationController *navigationController = [storyboard instantiateInitialViewController];
    
    return navigationController;
}

3 参考示例

博主模仿老版本Xcode提供的 "Master-Detail" 模版做了一个类似的App,在 iPhone 中采用的是树形导航(Navigation + TableView),在 iPad 中采用的是分屏导航(Split)。

点击加号,在表视图中添加一条当前时间的记录:

点击记录,跳转到Detail页面获取详细信息:

在 iPad 平台运行的效果如下:

项目链接:

https://gitee.com/da-guan-mu-lao-sheng/objc-IOS/tree/master/iOS-Apps/MyNotes/MyNotes