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 */; };
|
||||
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 */; };
|
||||
D5A98CE2284EF14B00E023E5 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A98CE1284EF14B00E023E5 /* SceneDelegate.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@ -365,6 +366,7 @@
|
||||
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>"; };
|
||||
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; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
@ -828,6 +830,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BFFA71DC1AAC406100EE9DD1 /* AppDelegate.swift */,
|
||||
D5A98CE1284EF14B00E023E5 /* SceneDelegate.swift */,
|
||||
BFFA71E01AAC406100EE9DD1 /* Main.storyboard */,
|
||||
BFFC46211D59848000AF2CC6 /* Launch */,
|
||||
BF46894D1AAC469800A2586D /* Game Selection */,
|
||||
@ -1192,6 +1195,7 @@
|
||||
BF797A2D1C2D339F00F1A000 /* UILabel+FontSize.swift in Sources */,
|
||||
BF80E1D21F13117000847008 /* ControllerInputsViewController.swift in Sources */,
|
||||
BF5942641E09BBB10051894B /* LoadControllerSkinImageOperation.swift in Sources */,
|
||||
D5A98CE2284EF14B00E023E5 /* SceneDelegate.swift in Sources */,
|
||||
BFE56E1923EB7BE00014FECD /* UIImage+SymbolFallback.swift in Sources */,
|
||||
BF6EE5E91F7C5F860051AD6C /* _GameControllerInputMapping.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
|
||||
{
|
||||
func registerCores()
|
||||
|
||||
@ -23,8 +23,16 @@ extension UIViewController
|
||||
struct DeepLinkController
|
||||
{
|
||||
private var window: UIWindow? {
|
||||
guard let delegate = UIApplication.shared.delegate, let window = delegate.window else { return nil }
|
||||
return window
|
||||
if #available(iOS 13, *)
|
||||
{
|
||||
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? {
|
||||
|
||||
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>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<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>
|
||||
<array/>
|
||||
<key>UIFileSharingEnabled</key>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user