Swift: avoid to force unwrap constant variable - ios

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
}

Related

Keep property in memory forever

I want to add Reachability library to my app, and there is what we can read in doc:
//declare this property where it won't go out of scope relative to your listener
let reachability = try! Reachability()
So, what I did is:
Create Singleton object to do stuff:
class ReachabilityService {
static let shared = ReachabilityService()
private init() {}
private let reachability = try! Reachability()
}
Did add property to AppDelegate to keep it in memory for application life:
class AppDelegate: UIResponder, UIApplicationDelegate {
let reachability = ReachabilityService.shared
}
My question is, will reachability property in AppDelegate be in memory for all of application lifetime?
Yes, the property declared in AppDelegate will be available throughout the lifecycle of the application.

UIApplication Instance fail

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

UIApplication.delegate must be used from main thread only [duplicate]

This question already has answers here:
-[UIApplication delegate] must be called from main thread only
(2 answers)
Closed 5 years ago.
I have the following code in my app delegate as a shortcut for working with CoreData in my other viewControllers:
let ad = UIApplication.shared.delegate as! AppDelegate
let context = ad.persistentContainer.viewContext
However, I now get the error message:
"UI API called from background thread" and "UIApplication.delegate must be used from main thread only".
I am working with CoreData while my app is in the background, but this is the first time I've seen this error message. Does anybody know what's going on here?
Update: I tried to move this inside the appDelegate class itself, and using the following code -
let dispatch = DispatchQueue.main.async {
let ad = UIApplication.shared.delegate as! AppDelegate
let context = ad.persistentContainer.viewContext
}
Now, I can no longer access the ad and context variables outside the AppDelegate. Is there something I'm missing?
With ref to this (-[UIApplication delegate] must be called from main thread only) in Swift (for your query resolution)
DispatchQueue.main.async(execute: {
// Handle further UI related operations here....
//let ad = UIApplication.shared.delegate as! AppDelegate
//let context = ad.persistentContainer.viewContext
})
With edit: (Where is the correct place to declare ad and context? Should I declare these in my viewControllers in the main dispatch)
Place of variables (ad and context) declaration defines scope for it. You need to decide what would be scope of these variable. You can declare them Project or application level (Globally), class level or particular this function level.
If you want to use these variable in other ViewControllers then declare it globally or class level with public/open/internal access control.
var ad: AppDelegate! //or var ad: AppDelegate?
var context: NSManagedObjectContext! //or var context: NSManagedObjectContext?
DispatchQueue.main.async(execute: {
// Handle further UI related operations here....
ad = UIApplication.shared.delegate as! AppDelegate
context = ad.persistentContainer.viewContext
//or
//self.ad = UIApplication.shared.delegate as! AppDelegate
//self.context = ad.persistentContainer.viewContext
})

how can i declare a variable or function globally as we declare in Objective C Macros

I want to make some functions and variables globally so that i can access those function and variables from any where
class:GlobalClass{
let appDelegate = UIApplication.shared.delegate as! AppDelegate
}
i am using a global class but every time when i want to use function i have to initialize the GlobalClass like:
GlobalClass().appDelegate
you can achieve this by create a new file of name GlobalClass and import UIKit and Foundation in that class
and put your variable and function directly in this file like:-
import UIKit
import Foundation
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let scree_width = UIScreen.main.bounds.width
func status()->Bool{
return true
}
you can access the variables and funnctions of this file any where like this:-
appDelegate
status()

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.

Resources