UIApplication Instance fail - ios

if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
// FAIL
}
But If I do UIApplication.shared.delegate then I'm getting Optional<UIApplicationDelegate>
Please help.
AppDelegate: https://gist.github.com/n1tesh/8f069e3b4eb9d843e691f5d463b81017

with UIApplication.shared.delegate you are getting
Optional<UIApplicationDelegate> is actually protocol, and with this line
if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
you are checking that some class named AppDelegate is confirming that protocol. If your if condition fails that means that your AppDelegate is not confirm UIApplicationDelegate protocol methods. and not related but also confirm #UIApplicationMain is there in top of AppDelegate class

Related

iOS - Calling SceneDelegate method from ViewController

I tried following code to call Scene Delegate func from a VC and getting error
Thread 1: signal SIGABRT
let sceneDelegate = UIApplication.shared.delegate as! SceneDelegate
sceneDelegate.initializeFirstViewController()
Is there any way i can call SceneDelegate func from VC?
UIApplication.shared.delegate is AppDelegate not SceneDelegate You need
if let scene = UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate {
// to do
}

Swift: avoid to force unwrap constant variable

I'm trying to avoid a force unwrap of global variables. How can I do that in this particular example:
let AppDelegate = UIApplication.shared.delegate as! AppDelegate
If you don't want to force-unwrap (which is fine here in this case), then use if let.
if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
// Do something with appDelegate
}
But the force-unwrap is fine for this. You want the app to crash during development if you make a typo on the type of the app delegate. It will never fail at runtime unless you make a change to the code and ship it to Apple without at least running your app once.
Made this an extension so no copy paste anymore. This is as type safe as it gets since it only makes sense for the AppDelegate to implement UIApplicationDelegate and the one is always reachable via UIApplication.shared.delegate.
#if os(macOS)
import Cocoa
typealias ApplicationDelegate = NSApplicationDelegate
typealias Application = NSApplication
#else
import UIKit
typealias ApplicationDelegate = UIApplicationDelegate
typealias Application = UIApplication
#endif
public extension ApplicationDelegate {
static var shared: Self {
return Application.shared.delegate as! Self
}
}
If you want to use the variable locally then:
if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
//logic here
}
or
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {return}
I don't think there is a way to use AppDelegate globally without using force casting.
Edited
To create a global variable, just declare it anywhere outside a class. For example:
var globalVariable = 1
class Person {
//logic here
}

How do I refactor my code to call AppDelegate on the main thread?

I recently started migrating my project from Swift3/Xcode8 to Swift4/Xcode9. My app crashes at runtime because the main thread sanitizer allows access to UIApplication.shared.delegate only on the main thread, resulting in a crash at startup. I have the following code, which worked fine in Swift 3 -
static var appDelegate: AppDelegate {
return UIApplication.shared.delegate as! AppDelegate;
}
Other classes in my code make access to appDelegate. I need to figure out a way to return UIApplication.shared.delegate from the main thread.
Note: Using an DispatchQueue.main.async{} block from wherever access is made to appDelegate is not an option. Need to use it only within the static var appDelegate declaration only.
Looking for a clever workaround.
Relevant crash message:
Main Thread Checker: UI API called on a background thread: -[UIApplication delegate]
PID: 1094, TID: 30824, Thread name: (none), Queue name: NSOperationQueue 0x60400043c540 (QOS: UNSPECIFIED), QoS: 0
Solved by using Dispatch Groups.
static var realDelegate: AppDelegate?;
static var appDelegate: AppDelegate {
if Thread.isMainThread{
return UIApplication.shared.delegate as! AppDelegate;
}
let dg = DispatchGroup();
dg.enter()
DispatchQueue.main.async{
realDelegate = UIApplication.shared.delegate as? AppDelegate;
dg.leave();
}
dg.wait();
return realDelegate!;
}
and call it somewhere else for
let appDelegate = AppDelegate(). realDelegate!
I use the following:
static var shared: AppDelegate? {
if Thread.isMainThread {
return UIApplication.shared.delegate as? AppDelegate
}
var appDelegate: AppDelegate?
DispatchQueue.main.sync {
appDelegate = UIApplication.shared.delegate as? AppDelegate
}
return appDelegate
}

Swift: getting AppDelegate instance as a class func results in Thread 1: EXC_BAD_INSTRUCTION

I want to get my AppDelegate reference from a class func in my AppDelegate. Why is this throwing a Thread 1: EXC_BAD_INSTRUCTION?
class func getDelegate() -> AppDelegate {
return UIApplication.sharedApplication().delegate as! AppDelegate
}
I have also tried to move this to another utility class and as a regular func, but getting the same crash.
Is there a way I can access the AppDelegate as a class func instead of having to write
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
in every class?
Declare class function to get appDelegate in AppDelegate class as
class func getDelegate() -> AppDelegate {
return UIApplication.sharedApplication().delegate as! AppDelegate
}
To access and use appDelegate in other class, call
let delegate = AppDelegate.getDelegate()
delegate.printHello()
Create a class as shown below[in a new class file or in existing class file outside the previous class. No need to put it inside AppDelete.swift file]
class Delegate
{
static var appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
}
and you can use it as Delegate.appDelegate in any class.

Call app delegate method from view controller

I want to know if I can call an app delegate method from another ViewController.
When the app starts, the application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool i method is called. Can I call this method a second time from another view controller?
Not sure why you want to do this. You probably shouldn't, but for the purpose of answering the question here it is:
// get a reference to the app delegate
let appDelegate: AppDelegate? = UIApplication.shared.delegate as? AppDelegate
// call didFinishLaunchWithOptions ... why?
appDelegate?.application(UIApplication.shared, didFinishLaunchingWithOptions: nil)
In Swift 3.0, you can call as:
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.anyAppDelegateInstaceMethod()
This method is called just once when app launches. You can't from ViewController. Instead make user defined method in AppDelegete. and call that method from ViewController. By getting object of AppDelegate.
AppDelegate *appDel = (AppDelegate *)[UIApplication sharedApplication].delegate;
[appDel <Your method>];
Constructors:
Add a constructor in AppDelegate Class at the end of code
Swift 3.x
class func shared() -> AppDelegate
{
return UIApplication.shared.delegate as! AppDelegate
}
Swift 2.x
func appDelegate () -> AppDelegate
{
return UIApplication.sharedApplication().delegate as! AppDelegate
}
and add a var like this
var boolForFun = Bool()
How to use reference in your class?
Method
for swift 3x
access functins or variables
AppDelegate.shared().boolForFun = true
for else
appDelegate().methodFoo()
Variable
appDelegate().foo
Swift 4, Swift 5
As others have said you shouldn't do that.
It would be better if you trigger it when you are in a certain application life cycle and do something specific using the Notification Center.
Example (in ViewController):
NotificationCenter.default.addObserver(
self,
selector: #selector(applicationWillEnterForeground),
name: UIApplication.willEnterForegroundNotification,
object: nil
)
However, if you do have to call the app delegate method, you can use this
let appDelegate: AppDelegate? = UIApplication.shared.delegate as? AppDelegate

Resources