Switches to UIScene-based app lifecycle
This commit is contained in:
parent
4829b393c5
commit
52a68e28dd
@ -169,6 +169,7 @@
|
|||||||
D524F4A3273DE9C000D500B2 /* ProcessInfo+JIT.swift in Sources */ = {isa = PBXBuildFile; fileRef = D524F4A2273DE9C000D500B2 /* ProcessInfo+JIT.swift */; };
|
D524F4A3273DE9C000D500B2 /* ProcessInfo+JIT.swift in Sources */ = {isa = PBXBuildFile; fileRef = D524F4A2273DE9C000D500B2 /* ProcessInfo+JIT.swift */; };
|
||||||
D524F4A5273DEBB400D500B2 /* ServerManager+Delta.swift in Sources */ = {isa = PBXBuildFile; fileRef = D524F4A4273DEBB400D500B2 /* ServerManager+Delta.swift */; };
|
D524F4A5273DEBB400D500B2 /* ServerManager+Delta.swift in Sources */ = {isa = PBXBuildFile; fileRef = D524F4A4273DEBB400D500B2 /* ServerManager+Delta.swift */; };
|
||||||
D5011C48281B6E8B00A0760B /* CharacterSet+Filename.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5011C47281B6E8B00A0760B /* CharacterSet+Filename.swift */; };
|
D5011C48281B6E8B00A0760B /* CharacterSet+Filename.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5011C47281B6E8B00A0760B /* CharacterSet+Filename.swift */; };
|
||||||
|
D5A98CE2284EF14B00E023E5 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A98CE1284EF14B00E023E5 /* SceneDelegate.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
@ -365,6 +366,7 @@
|
|||||||
D524F4A2273DE9C000D500B2 /* ProcessInfo+JIT.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProcessInfo+JIT.swift"; sourceTree = "<group>"; };
|
D524F4A2273DE9C000D500B2 /* ProcessInfo+JIT.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProcessInfo+JIT.swift"; sourceTree = "<group>"; };
|
||||||
D524F4A4273DEBB400D500B2 /* ServerManager+Delta.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ServerManager+Delta.swift"; sourceTree = "<group>"; };
|
D524F4A4273DEBB400D500B2 /* ServerManager+Delta.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ServerManager+Delta.swift"; sourceTree = "<group>"; };
|
||||||
D5011C47281B6E8B00A0760B /* CharacterSet+Filename.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CharacterSet+Filename.swift"; sourceTree = "<group>"; };
|
D5011C47281B6E8B00A0760B /* CharacterSet+Filename.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CharacterSet+Filename.swift"; sourceTree = "<group>"; };
|
||||||
|
D5A98CE1284EF14B00E023E5 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
|
||||||
DC866E433B3BA9AE18ABA1EC /* libPods-Delta.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Delta.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
DC866E433B3BA9AE18ABA1EC /* libPods-Delta.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Delta.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
@ -828,6 +830,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
BFFA71DC1AAC406100EE9DD1 /* AppDelegate.swift */,
|
BFFA71DC1AAC406100EE9DD1 /* AppDelegate.swift */,
|
||||||
|
D5A98CE1284EF14B00E023E5 /* SceneDelegate.swift */,
|
||||||
BFFA71E01AAC406100EE9DD1 /* Main.storyboard */,
|
BFFA71E01AAC406100EE9DD1 /* Main.storyboard */,
|
||||||
BFFC46211D59848000AF2CC6 /* Launch */,
|
BFFC46211D59848000AF2CC6 /* Launch */,
|
||||||
BF46894D1AAC469800A2586D /* Game Selection */,
|
BF46894D1AAC469800A2586D /* Game Selection */,
|
||||||
@ -1192,6 +1195,7 @@
|
|||||||
BF797A2D1C2D339F00F1A000 /* UILabel+FontSize.swift in Sources */,
|
BF797A2D1C2D339F00F1A000 /* UILabel+FontSize.swift in Sources */,
|
||||||
BF80E1D21F13117000847008 /* ControllerInputsViewController.swift in Sources */,
|
BF80E1D21F13117000847008 /* ControllerInputsViewController.swift in Sources */,
|
||||||
BF5942641E09BBB10051894B /* LoadControllerSkinImageOperation.swift in Sources */,
|
BF5942641E09BBB10051894B /* LoadControllerSkinImageOperation.swift in Sources */,
|
||||||
|
D5A98CE2284EF14B00E023E5 /* SceneDelegate.swift in Sources */,
|
||||||
BFE56E1923EB7BE00014FECD /* UIImage+SymbolFallback.swift in Sources */,
|
BFE56E1923EB7BE00014FECD /* UIImage+SymbolFallback.swift in Sources */,
|
||||||
BF6EE5E91F7C5F860051AD6C /* _GameControllerInputMapping.swift in Sources */,
|
BF6EE5E91F7C5F860051AD6C /* _GameControllerInputMapping.swift in Sources */,
|
||||||
BF5942871E09BC8B0051894B /* _ControllerSkin.swift in Sources */,
|
BF5942871E09BC8B0051894B /* _ControllerSkin.swift in Sources */,
|
||||||
|
|||||||
@ -114,6 +114,24 @@ class AppDelegate: UIResponder, UIApplicationDelegate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@available(iOS 13, *)
|
||||||
|
extension AppDelegate
|
||||||
|
{
|
||||||
|
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration
|
||||||
|
{
|
||||||
|
// Called when a new scene session is being created.
|
||||||
|
// Use this method to select a configuration to create the new scene with.
|
||||||
|
return UISceneConfiguration(name: "Main", sessionRole: connectingSceneSession.role)
|
||||||
|
}
|
||||||
|
|
||||||
|
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>)
|
||||||
|
{
|
||||||
|
// Called when the user discards a scene session.
|
||||||
|
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
|
||||||
|
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private extension AppDelegate
|
private extension AppDelegate
|
||||||
{
|
{
|
||||||
func registerCores()
|
func registerCores()
|
||||||
|
|||||||
@ -23,8 +23,16 @@ extension UIViewController
|
|||||||
struct DeepLinkController
|
struct DeepLinkController
|
||||||
{
|
{
|
||||||
private var window: UIWindow? {
|
private var window: UIWindow? {
|
||||||
guard let delegate = UIApplication.shared.delegate, let window = delegate.window else { return nil }
|
if #available(iOS 13, *)
|
||||||
return window
|
{
|
||||||
|
guard let delegate = UIApplication.shared.connectedScenes.lazy.compactMap({ $0.delegate as? UIWindowSceneDelegate }).first, let window = delegate.window else { return nil }
|
||||||
|
return window
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
guard let delegate = UIApplication.shared.delegate, let window = delegate.window else { return nil }
|
||||||
|
return window
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var topViewController: UIViewController? {
|
private var topViewController: UIViewController? {
|
||||||
|
|||||||
175
Delta/SceneDelegate.swift
Normal file
175
Delta/SceneDelegate.swift
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
//
|
||||||
|
// SceneDelegate.swift
|
||||||
|
// Delta
|
||||||
|
//
|
||||||
|
// Created by Riley Testut on 6/6/22.
|
||||||
|
// Copyright © 2022 Riley Testut. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
import DeltaCore
|
||||||
|
import Harmony
|
||||||
|
|
||||||
|
@objc(SceneDelegate) @available(iOS 13, *)
|
||||||
|
class SceneDelegate: UIResponder, UIWindowSceneDelegate
|
||||||
|
{
|
||||||
|
var window: UIWindow?
|
||||||
|
|
||||||
|
private let deepLinkController = DeepLinkController()
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
|
self.window?.tintColor = .deltaPurple
|
||||||
|
|
||||||
|
if let context = connectionOptions.urlContexts.first
|
||||||
|
{
|
||||||
|
self.handle(.url(context.url))
|
||||||
|
}
|
||||||
|
|
||||||
|
if let shortcutItem = connectionOptions.shortcutItem
|
||||||
|
{
|
||||||
|
self.handle(.shortcut(shortcutItem))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 necessarily 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.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(iOS 13, *)
|
||||||
|
extension SceneDelegate
|
||||||
|
{
|
||||||
|
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>)
|
||||||
|
{
|
||||||
|
guard let context = URLContexts.first else { return }
|
||||||
|
self.handle(.url(context.url))
|
||||||
|
}
|
||||||
|
|
||||||
|
func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void)
|
||||||
|
{
|
||||||
|
self.handle(.shortcut(shortcutItem))
|
||||||
|
completionHandler(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(iOS 13, *)
|
||||||
|
private extension SceneDelegate
|
||||||
|
{
|
||||||
|
func handle(_ deepLink: DeepLink)
|
||||||
|
{
|
||||||
|
guard DatabaseManager.shared.isStarted else {
|
||||||
|
// Wait until DatabaseManager is ready before handling deep link.
|
||||||
|
|
||||||
|
// NotificationCenter.default.notifications requires iOS 15 or later :(
|
||||||
|
// _ = await NotificationCenter.default.notifications(named: DatabaseManager.didStartNotification).first(where: { _ in true })
|
||||||
|
|
||||||
|
var observer: NSObjectProtocol?
|
||||||
|
observer = NotificationCenter.default.addObserver(forName: DatabaseManager.didStartNotification, object: DatabaseManager.shared, queue: .main) { [weak observer] _ in
|
||||||
|
observer.map { NotificationCenter.default.removeObserver($0) }
|
||||||
|
self.handle(deepLink)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
// DeepLinkController expects to be called from main thread.
|
||||||
|
|
||||||
|
switch deepLink
|
||||||
|
{
|
||||||
|
case .shortcut:
|
||||||
|
_ = self.deepLinkController.handle(deepLink)
|
||||||
|
|
||||||
|
case .url(let url):
|
||||||
|
if url.isFileURL
|
||||||
|
{
|
||||||
|
if GameType(fileExtension: url.pathExtension) != nil || url.pathExtension.lowercased() == "zip"
|
||||||
|
{
|
||||||
|
self.importGame(at: url)
|
||||||
|
}
|
||||||
|
else if url.pathExtension.lowercased() == "deltaskin"
|
||||||
|
{
|
||||||
|
self.importControllerSkin(at: url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if url.scheme?.hasPrefix("db-") == true
|
||||||
|
{
|
||||||
|
_ = DropboxService.shared.handleDropboxURL(url)
|
||||||
|
}
|
||||||
|
else if url.scheme?.lowercased() == "delta"
|
||||||
|
{
|
||||||
|
_ = self.deepLinkController.handle(deepLink)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func importGame(at url: URL)
|
||||||
|
{
|
||||||
|
DatabaseManager.shared.importGames(at: [url]) { (games, errors) in
|
||||||
|
if errors.count > 0
|
||||||
|
{
|
||||||
|
let alertController = UIAlertController.alertController(for: .games, with: errors)
|
||||||
|
self.present(alertController)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func importControllerSkin(at url: URL)
|
||||||
|
{
|
||||||
|
DatabaseManager.shared.importControllerSkins(at: [url]) { (games, errors) in
|
||||||
|
if errors.count > 0
|
||||||
|
{
|
||||||
|
let alertController = UIAlertController.alertController(for: .controllerSkins, with: errors)
|
||||||
|
self.present(alertController)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func present(_ alertController: UIAlertController)
|
||||||
|
{
|
||||||
|
var rootViewController = self.window?.rootViewController
|
||||||
|
|
||||||
|
while rootViewController?.presentedViewController != nil
|
||||||
|
{
|
||||||
|
rootViewController = rootViewController?.presentedViewController
|
||||||
|
}
|
||||||
|
|
||||||
|
rootViewController?.present(alertController, animated: true, completion: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -203,6 +203,27 @@
|
|||||||
<string>Delta uses your microphone to emulate the Nintendo DS microphone.</string>
|
<string>Delta uses your microphone to emulate the Nintendo DS microphone.</string>
|
||||||
<key>NSPhotoLibraryUsageDescription</key>
|
<key>NSPhotoLibraryUsageDescription</key>
|
||||||
<string>Press "OK" to allow Delta to use images from your Photo Library as game artwork.</string>
|
<string>Press "OK" to allow Delta to use images from your Photo Library as game artwork.</string>
|
||||||
|
<key>UIApplicationSceneManifest</key>
|
||||||
|
<dict>
|
||||||
|
<key>UIApplicationSupportsMultipleScenes</key>
|
||||||
|
<false/>
|
||||||
|
<key>UISceneConfigurations</key>
|
||||||
|
<dict>
|
||||||
|
<key>UIWindowSceneSessionRoleApplication</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>UILaunchStoryboardName</key>
|
||||||
|
<string>LaunchScreen</string>
|
||||||
|
<key>UISceneConfigurationName</key>
|
||||||
|
<string>Main</string>
|
||||||
|
<key>UISceneDelegateClassName</key>
|
||||||
|
<string>SceneDelegate</string>
|
||||||
|
<key>UISceneStoryboardFile</key>
|
||||||
|
<string>Main</string>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
<key>UIBackgroundModes</key>
|
<key>UIBackgroundModes</key>
|
||||||
<array/>
|
<array/>
|
||||||
<key>UIFileSharingEnabled</key>
|
<key>UIFileSharingEnabled</key>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user