技术标签: # Xcode iOS 13 Xcode11 SceneAppdelegate
如果将Xcode更新到11, 创建项目。默认会创建SceneDelegate.swift, 那么问题来了, 这个代理用来干嘛的了?
在这篇文章中,我们将探索iOS13和Xcode11的改变。我们着重介绍scene和Delegates , 看看他们事如何影响SwiftUI,Storyboard和Xib构建的UI.
我们将学习到:
系好安全带,发车。。。
这篇文档项目环境Xcode11 和 iOS13
我们对于AppDelegate非常熟悉,他是一个App启动的入口,其中的 application(_:didFinishLaunchingWithOptins: ) 方法是系统操作唤醒的第一个方法。
AppDelegate 遵守UIKit框架的UIApplicationDeleaget ,但是在iOS13中app delegate发生了改变 ,我们能很快发现。
以下是iOS12 app deleget 的常规操作:
使用Storyboard启动的app, app delegate都是千篇一律的。因为它只返回true 就像下面这个方法:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
{
return true
}
一个简单的使用Xib的app, 需要设置自己的根控制器,就像这样:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
{
let timeline = TimelineViewController()
let navigation = UINavigationController(rootViewController: timeline)
let frame = UIScreen.main.bounds
window = UIWindow(frame: frame)
window!.rootViewController = navigation
window!.makeKeyAndVisible()
return true
}
在上面的代码中,我们创建了一个控制器, 并且把他放在导航栏控制器中,把他分配为给 UIWindow对象的rootController属性。 这个window对象是 app delegate的属性, 是我们app拥有的一个window.
app的window是iOS中一个非常重要的概念, 一般一个window就是一个app,而且大部分iOS 应用只有一个window, 它就是你应用 UI界面的可视, 用户点击事件, 提供后台显示内容。 当然这里的window和微软的Windows不是一个东西, 是不同的概念(谢谢你 Xerox!)。
好现在我们把重点放在scene delegate。
在iOS 13及以上 scene delegate 将扮演 一些 app delegate 的作用, 大多数情况窗口(window)的概念被场景(scene)替换。 一个应用可以有多个场景, 而场景又是作为应用的界面和内容的呈放。
一个app有多个场景的概念来说是特别地, 而且这样就允许您创建多窗口的iOS或者iPadOS应用。在一个 文本处理app中,每一个文档都可以有自己的场景。例如, 用户可以创建一个场景的复制场景, 一次可以运行一个app的多实例。
在Xcode 11中跳转使用scene delegate有三个地方:
好,让我们一步一步操作。
SceneDelegate类如:
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.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).
guard let _ = (scene as? UIWindowScene) else { return }
}
func sceneDidDisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
}
func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}
func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}
func sceneWillEnterForeground(_ scene: UIScene) {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}
}
场景代理中最重要的方法是 scene(_:willConnectTo:options:), 一般来说它等同于iOS 13之前的 application(_: didFinishLaunchingWithOptions:)方法, 场景被添加到app,这个方法将被调用, 这是配置场景完美的地方。 在上面的代码中, 我们可以设置controller栈,这个设置我们等会儿再说
重点注意SceneDelegate在使用delegate时,当然 一个delegate 也可以响应任何场景,如果你想使用一个代理配置所有场景的话。
SceneDelegate也包含下面这些方法:
在iOS13中, Appdelegate类现在包含了与secene sessions 相关的方法。 创建一个场景的同是 场景对象也会随之创建,场景会话对象跟踪管理场景的相关信息, 方法如下:
现在, 场景会话用于指定一个场景, 比如 "External Display" 或者 "CardPlay", 也被用来存储一个场景的状态, 用于状态恢复非常好用。 状态恢复允许你恢复或者再次创建UI在app启动期间。你也可以分配用户信息到场景会话中, 这是一个你可以放入任何能放入的字典。
application(_:didDiscardSceneSession:) 是非常简单的, 当用户通过应用切换来关闭一个或者多个场景时会调用。你可以在这里释放一些你场景使用的资源,因为他们不在需要使用了。
对比与 sceneDidDisconnect(_:) , 这个方法标识当场景仅仅失去连接,但是不一定丢弃。 它可能会尝试重连, 直到application(_:didDiscardSceneSession:) 使用应用切换标记场景退出。
你使用的每一个场景都需要在应用场景清单中声明过, 简而言之就是清单列出你应用支持的场景。 大多是app只有一个场景,但是你能创建更多个,比如响应通知或者事件的单独场景。
应用场景清单也是Info.plist文件中的一部分,Info.plist也是一个明确知道应用配置的好地方。该文件属性列表包含应用名字,版本号,支持设备方向等
注意在这里声明session的类型, 而不是session本身。 你的app能支持一个场景, 创建一个场景的副本和使用它来创建多窗口app.
以下是Info.plist的列表大概:
在顶层,你可以看见应用场景清单子项,下面时Enable Multiple Windows ,如果你需要支持多窗口,需要设置为YES. 再往下是一个声明应用内场景的Applicaiton Session Role数组。 另一个部分能用于声明外部场景。
最重要的信息是Application Session Role 数组部分, 包括:
storyboard的名字部分主要提醒用户主Storyboard,以便于在Xcode 12 的项目属性配置中看到。 一般基本iOS 应用中, 如果你不使用场景这就是你设置或改变主要Storyboard的地方【译者发现,如果需要改变主显示Storyboard,只能在这里修改,直接在项目的General -> Deployment Info -> Main Interface中修改是没有效果的。 】。
如何用SceneDelegate、 AppDelegate中的scene session 应用场景清单怎么创建多窗口app?
太棒了!有了初步了解,我们看看用Xcode11创建UI,看看是如何影响的。
iOS13最简单创建项目方法是使用SwiftUI, 简单来说 SwfitUI创建的项目大多是都是通过SceneDelegate设置初始化UI的
首先看看SwiftUI的应用场景清单长什么样子:
这是非常标准的,对于默认app,哪里标准了? 使用Default Configuration标识不包含的Storyboard Name Set 。记住, 如果你想支持多窗口,需要吧Enable Multiple Windows 设置为 YES.
我们跳过AppDelegate, 因为它非常标准,只返回true.
下一步, 看看 SceneDelegate类, 在我们修改之前,场景代理设置了你应用的场景响应。和设置她们的初始化视图。
就像这样:
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
let contentView = ContentView()
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
}
上面的代码做了什么了?
首先,认真考虑scene(_:willConnetectTo:options:)协议方法(当一个新场景加入),提供scene对象和session, 这个UIWindowScene对象是app创建的,如此一来你就不需要手动创建。
之后,这个window属性被使用,应用仍然有UIWindow的window对象,只不过现在他们是场景的一部分。在代码中,在if let 闭包内,你可以清楚的看见使用scene参数初始化的UIWindow实例。
设置window的rootViewController属性,然后这个window变为可见(make key add visible),目的是把它放在UI层的最前面。
使用SwiftUI,你要注意,被创建的ContentView作为root view controller 通过使用UIHostingController, 这个控制器把SwiftUI基本视图放在屏幕上。
方法中有一点注意,类型为UIScene的scene参数,实际上UIWindowScene类型的实例。使用as 可选解析(到目前为止,创建的场景通常是UIWindowScene类型,但我猜想在未来,我们会看到更多类型的场景。)
所有的看起来很复杂,但是总体来看非常简单。
非常棒!让我们开始
你可以使用Xcode11创建基本项目, 选择SwfitUI, 通过选择File -> New -> Project, 之后选择 Single View App, 最后选择 SwiftUI作为User Interface
Storyboards, XIBs, 是创建UI的有效的方式。 但是在iOS 13上是一样的。在以后,我们会看到越来越多SwiftUI 应用, 但是现在, storyboard更常用。
有趣的是,你无法多余操作,只需要选择File-> New -> Project, 选择Single View App, 最后选择 Storyboard作为User Interface , 就完成了。
下面使步骤:
很开发者使用代码创建UI, 随着SwiftUI的崛起, 我们能看到更多。 那如果你不是用Storyboard,而是使用xib来创建你得app UI , 来看看场景代理如何适配它吧。
首先, app delegate 和 Applicaton Scene Manifest 使完整的, 默认设置的。 我们没有使用storyboard,我们要在 SceneDelegate 的 scene(_:willConnectTo: options:)方法内设置初始化控制器。
就像这样:
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions)
{
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
let timeline = TimelineViewController()
let navigation = UINavigationController(rootViewController: timeline)
window.rootViewController = navigation
self.window = window
window.makeKeyAndVisible()
}
}
我们来看看发生了啥:
很简单,对吧? 最核心的是,把你之前在app delegate中代码移到scene delegate ,配置Applicaton Scene Manifest
还在找怎么为已存在的项目添加场景支持吗? 看这个吧
完美了!这只是示例的一小部分, 随着我们的深入,场景代理允许你添加多窗口应用
你可能已经学会怎样为SwiftUI、Storyboard设置场景代理, 我们也看了使场景工作的三部分:app delegate , scene delegate , Application Scene Manifest , 非常棒!
想要学习更多吗? 通过下面资源学习吧:
logrotate使用中出现过的问题:1、logrotate 的配置文件必须是 root 644权限2、logrotate配置中的日志的目录权限不能为777,可以为7553、使用create和compress进行日志转存时,会有概率出现转存后的日志没有进行压缩,增加delaycompress4、使用copytruncate可以避免上面的那个问题,但是日志较大时会出现时间转存时间很久5、当即将生成的...
这里暂时就不做代码讲解了,代码亲测可用,里边的注释已经比较详细了,不明白的请自行查阅相关资料。代码如下:代码中用到的视频下载链接:https://pan.baidu.com/s/1bpwI1Uv 密码:s65y//opencv版本:OpenCV3.0//VS版本:VS2013//Author:qxsf321.net#include <opencv2/opencv.hpp&...
Mybatis-plus IPage分页常见问题(坑)1.TooManyResultsException观前提示:本文所使用的IDEA版本为ultimate 2019.1,JDK版本为1.8.0_141。1.TooManyResultsException最近在使用Mybatis-plus的IPage插件分页时,出现了以下的莫名其妙的错误Resolved [org.mybatis.spring.MyBatisSystemException: nested exception is org.apach
curl_global_init(CURL_GLOBAL_ALL);curl_global_cleanup();这两个是libcurl全局函数,负责环境的初始化和清理。非线程安全,对于多线程来说,请不要再每个线程里都初始化和清理。一个简单的做法是在主线程里初始化和清理。This function sets up the program environment tha_1671465600
Tomcat配置优化 调整tomcat参数进行优化 调整JVM参数进行优化 解读jvm字节码 代码优化
欢迎使用Markdown编辑器你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。新的改变我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:全新的界面设计 ,将会带来全新的写作体...
https://blog.csdn.net/LJFPHP/article/details/82705764
数据质量监控工具-Apache Griffin本地安装和调试1 、Apache Griffin简介Griffin起源于eBay中国,并于2016年12月进入Apache孵化器,Apache软件基金会2018年12月12日正式宣布Apache Griffin毕业成为Apache顶级项目。Griffin是属于模型驱动的方案,基于目标数据集合或者源数据集(基准数据),用户可以选择不同的数据质量维度...
中文文档: http://sklearn.apachecn.org/cn/stable/modules/ensemble.html英文文档: http://sklearn.apachecn.org/en/stable/modules/ensemble.html官方文档: http://scikit-learn.org/stable/
黑马头条项目是模拟今日头条开发的项目,总共分为十六章,下面给大家手写总结一下项目内容,希望给小伙伴们解答困惑(从今天开始,会不断更新的哦) 一. 环境搭建二. 平台管理端数据准备三. 用户认证四. 自媒体素材管理五. 自媒体文章发布六. kafka及第三方接口七. 自媒体文章审核八. 分布式任务调度及人工审核九. APP端基本功能展示十. APP端用户行为处理十一. APP端评论系统开发十二. APP端文章搜索十三. 新热文章计算十四. 项目部.
Android4.4 增加的/system/priv-app 跟 原来的/system/app 有啥区别呢?/system/priv-app中包括Launcher,systemui, settingsprovider等,均是系统的核心应用,这些应用能使用系统级的权限,4.4之前的所有/system/app下的软件都能使用系统级的权限。Androi
初始化一个Express项目,通过生成器工具express-generator快速生成了一个Express应用。1.安装express生成器 检查express版本 $express --version 可以查看版本npm i -g express-generator2.初始化一个express引用express express-app目录结构:...