SwiftUI AppDelegate UIWindow redeclaration - ios

I'm using SwiftUI so the AppDelegate is added by
#UIApplicationDelegateAdaptor(MyAppDelegate.self) var myAppDelegate
All delegate callbacks work fine, but var window: UIWindow? can't be redeclared.
Adding it to MyAppDelegate has no effect as if accessing UIApplication.shared.delegate class is not MyAppDelegate but SwiftUI.AppDlegate.
How I can add it to AppDelegate, to make it accessible by UIApplication.shared.delegate.window ?
Or how to set var window: UIWindow? property to SwiftUI.AppDlegate ?

Solution found. Custom MyAppDelegate can contain var window: UIWindow? property:
class MyAppDelegate: NSObject, ObservableObject, UIApplicationDelegate {
var window: UIWindow?
}
And can be accessed by EnvironmentVariable:
#EnvironmentObject private var appDelegate: MyAppDelegate
appDelegate.window = <Window object>
Then the correct UIWindow value will be available by UIApplication.shared.delegate.window
Documentation refference: https://developer.apple.com/documentation/swiftui/uiapplicationdelegateadaptor

Related

How to remove Scene Delegate from iOS Application?

I have created the iOS Project in Xcode 11.1. I need to remove scene delegate from the application.
You need to do the following steps:
Remove Scene delegate methods from App Delegate and delete the Scene delegate file.
You need to remove UIApplicationSceneManifest from Info.plist.
You also need to add var window:UIWindow? if it is not present in AppDelegate
Remove SceneDelegate.swift file
Remove Application Scene Manifest from Info.plist file
Add var window: UIWindow? to AppDelegate.swift
Replace #main with #UIApplicationMain
Remove UISceneSession Lifecycle ( functions ) in AppDelegate
It is a complete solution for empty project generated with Xcode (with storyboard)
Remove SceneDelegate.swift file
Remove Application Scene Manifest from Info.plist file
Paste this code to your AppDelegate.swift file
import UIKit
#main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window:UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController()
window?.makeKeyAndVisible()
return true
}
}
Adding on to milzi's answer
Remove SceneDelegate.swift file
Remove Application Scene Manifest from Info.plist file
Remove UISceneSession Lifecycle function from your AppDelegate class
Add var window: UIWindow? in your AppDelegate class as a instance property
Replace #main attribute with #UIApplicationMain attribute (This saves as to manually create and assign window)
Below is how you how your AppDelegate should look like after changes:
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
}
To add to accepted answer: you also need to write this in your AppDelegate:
self.window = UIWindow(frame: UIScreen.main.bounds)
let controller = MyRootViewController()
window?.rootViewController = controller
window?.makeKeyAndVisible()
Just in case if you are developing in Objective-C, add window property in the AppDelegate.h file like this:
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#end
No need to initialise the window. It will work automatically.

reason: '-[FaveoHelpdeskPro_Swift.AppDelegate window]: unrecognized selector sent to instance 0x282efc980'

I am getting following error when I am trying to run the project, my project is crashing.
It is giving following error,
FaveoHelpdeskPro_Swift[1400:370341]
-[FaveoHelpdeskPro_Swift.AppDelegate window]: unrecognized selector sent to instance 0x282efc980
and
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason:
'-[FaveoHelpdeskPro_Swift.AppDelegate window]: unrecognized selector
sent to instance 0x282efc980'
and it coming to following screen,
and my SceneDelegate.swift contains already window object,
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 }
}
what is the issue, why it is crashing ?
Here is the complete project
Your AppDelegate does not contain a window reference. Add a window variable in your AppDelegate
var window: UIWindow?
An excerpt from Apple's documentation
This property contains the window used to present the app’s visual content on the device’s main screen.
Implementation of this property is required if your app’s Info.plist file contains the UIMainStoryboardFile key
When you start to init your main ViewController in SceneDelegate in the project and some UI libraries (like SVProgressHUD,...) still point to AppDelegate's window and nothing there, so it crashes. I have met and successfully fixed this problem following this way:
Declare an UIWindow in AppDelegate if it's not there, also declare a static variable for fast access to AppDelegate:
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow? // HERE, add it if it's not available.
static var shared: AppDelegate { return UIApplication.shared.delegate as! AppDelegate }
//...
}
In SceneDelegate, make a reference of UIWindow object back to AppDelegate:
#available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow? // HERE
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(frame: windowScene.coordinateSpace.bounds)
window?.windowScene = windowScene
window?.rootViewController = YOUR_VIEW_CONTROLLER()
window?.makeKeyAndVisible()
AppDelegate.shared.window = window // Connect it HERE!
}
// ....
}
Note: If you just finish step 1, it will not crash but some UI component will display wrong because they cannot determine which is the main Window.
So what I just did is I added a UIWindow var to my AppDelegate like so:
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
...
Then in the SceneDelegate, when I am setting the UIWindow property:
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(frame: windowScene.coordinateSpace.bounds)
window?.rootViewController = MainTabBarController()
window?.windowScene = windowScene
window?.makeKeyAndVisible()
I also set it for the AppDelegate as well right below like so:
if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
appDelegate.window = window
}

Swift - App Delegate not passing data

I'm developing an App that it's data is from a URL, here's a sample code that I'm using
AppDelegate.swift
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var fromUrl: String!
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject)-> Bool {
print("Host: \(url.host!)")
self.fromUrl = url.host!
return true
}
ViewController.swift
import UIKit
class ViewController: UIViewController {
let appDelegate = AppDelegate()
override func viewDidLoad() {
super.viewDidLoad()
print(appDelegate.fromUrl)
}
It's is logging the url.host from app delegate. But when i try to log the value of fromUrl from the ViewController.swift it's returning nil. What do you think seems to be the problem? Thanks!
When you declare let appDelegate = AppDelegate() in ViewController you are actually instantiating another instance of AppDelegate. That is not the same instance that you are using as you actual ApplicationDelegate. Try getting that reference by using:
if let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate {
print(appDelegate.fromUrl)
}

Where to initialize the base class of my app in Swift

I have a class named Home which is the parent class of my app. Now, I want to initialize this class somewhere so that I can access everything inside the class from wherever I want. The starting point of the app is RootViewController. Should I initialize the app in the starting point? If yes, how should I do it so that it can be accessed from everywhere in the app?
As per my comment above, set a property on the AppDelegate class with the type Home, initialize it in application:didFinishLaunchingWithOptions. Now you can access this instance of home through the sharedApplication.delegate.
In AppDelegate.swift:
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var myHome: Home?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
// Override point for customization after application launch.
self.myHome = Home()
return true
}
Then access it in some other class:
let delegate = UIApplication.sharedApplication().delegate as AppDelegate
var home = delegate.myHome

How to use CoreLocation with swift?

I've tried using CoreLocation with my Swift app, but without luck. I have the following incredibly simple code:
(I've linked the CoreLocation library.)
import UIKit
import CoreLocation
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {
var window: UIWindow?
var locationManager: CLLocationManager = CLLocationManager()
locationManager.delegate = self
On the last line I get the error "Expected declaration."
What am I doing wrong?
Thanks in advance!
The following code locationManager.delegate = self is a statement. You need to execute it within one of the AppDelegate methods. For example:
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {
var window: UIWindow?
var locationManager: CLLocationManager = CLLocationManager()
func application(application :UIApplication, didFinishLaunchingWithOptions launchOptions:NSDictionary>) -> Bool {
locationManager.delegate = self
}
}

Resources