iOS的UIScene与多窗口

iPadOS 13开始支持多窗口。什么是多窗口?以系统自带的日历app为例:

日历app打开两个窗口

日历app可以打开多个窗口。但是多窗口并不是应用多开,虽然我们在多任务切换中可以看到貌似开了两个日历app,但它们只是日历app的两个窗口。

目前只有iPadOS支持多窗口,iOS并不支持多窗口。

多窗口的实现方式

为了实现多窗口,iPadOS 13引入了新的概念:scene(场景),每一个窗口就是一个scene。以前一个app只能存在一个key window,现在每个scene都有自己的key window。

如何使用scene

要使用scene,首先保证系统在iOS 13&iPadOS 13以上,然后对Xcode项目进行如下修改:

  1. Info.plist文件中添加Application Scene Manifest配置;
  2. 实现UIApplicationDelegate新增的管理scene生命周期的方法;
  3. 实现scene代理。

如果使用Xcode 11来创建新项目,会自带以上配置。如果是旧项目,就要手动添加以上配置了。

Application Scene Manifest

首先要在Info.plist文件里面添加Application Scene Manifest配置来让项目使用scene。

如果要让项目不使用scene,就要在Info.plist文件中删除Application Scene Manifest配置

Application Scene Manifest是一个字典,他有Enable Multiple Windows和Scene Configuration两个键:

Application Scene Manifest

Enable Multiple Windows是一个布尔值,标记该app是否支持多窗口。目前iOS是不支持多窗口的,只有iPadOS支持多窗口。如果你需要开发一个需要支持多窗口的iPad应用,那就需要设置为YES,否则就设置为NO就可以了。

就算不需要多窗口功能,也不妨使用scene来管理窗口,因为现在使用scene是Xcode的默认配置了。

Scene Configuration是一个字典,用来添加scene的配置信息:

Scene Configuration

有两种角色(role)的scene:External Display Session RoleApplication Session RoleExternal Display Session Role与使用外部显示设备有关,用的较少。一般配置Application Session Role就可以了。

可配置的scene信息有四个:Class NameConfiguration NameDelegate Class NameStoryboard Name,其中Configuration NameDelegate Class Name是必选的:

  1. Class Name。scene的类名,必须是UIScene的子类。如果是Application Session Role,必须是UIWindowScene的子类;
  2. Configuration Name。为这个配置起一个名字,必选值;
  3. Delegate Class Name。scene代理的类名,必须是实现UISceneDelegate的类,如果是Application Session Role,必须是实现UIWindowSceneDelegate的类。必选值;
  4. Storyboard Name。scene的窗口内容来源的Storyboard的名字,可选值。

scene对象和scene代理都不允许手动创建,只能在Info.plist中指定,然后由UIKit自动创建。

UIApplicationDelegate中管理scene生命周期的方法

UIApplicationDelegate为了支持scene新增两个方法:

#pragma mark -- UIScene Support --
// Called when the UIKit is about to create & vend a new UIScene instance to the application.
// The application delegate may modify the provided UISceneConfiguration within this method.
// If the UISceneConfiguration instance returned from this method does not have a systemType which matches the connectingSession's, UIKit will assert
- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options API_AVAILABLE(ios(13.0));

// Called when the system, due to a user interaction or a request from the application itself, removes one or more representation from the -[UIApplication openSessions] set
// If sessions are discarded while the application is not running, this method is called shortly after the applications next launch.
- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions API_AVAILABLE(ios(13.0));

其中-[application:configurationForConnectingSceneSession:options:]很重要,因为需要通过它获取scene的配置信息来创建新的scene:

- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
    UISceneConfiguration *config = [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
    return config;
}

-[UISceneConfiguration initWithName:sessionRole:]只能获取Info.plist中Application Scene Manifest已经填写的Scene Configure信息。

scene代理

scene代理,一个实现UISceneDelegate的类。如果是Application Session Role的scene,那就是一个实现UIWindowSceneDelegate的类。scene代理只能在Info.plist中的Scene Configuration指定,然后被UIKit自动创建。

对于Application Session Role的scene,需要创建root window。如果已经在Info.plist中的Scene Configuration指定了Storyboard Name,那么root window会自动从Storyboard中创建。如果没有指定Storyboard Name,那么就需要在-[UIWindowSceneDelegate scene:willConnectToSession:options:]中手动创建root window。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容