Matthew McDonnell Matthew McDonnell -4 years ago 190
iOS Question

Swift 3 access variables from App Delegate in View Controller

I am implementing google sign in on my app and I need to access the User ID and first/last name. The variables storing that data are in the App Delegate. I have searched the internet inside and out looking for how to do this in Swift 3, and there is absolutely nothing.

Here's the App Delegate (at least the part that matters):

class AppDelegate: UIResponder, UIApplicationDelegate, GIDSignInDelegate {

var window: UIWindow?
var databaseRef: FIRDatabaseReference!

var userID = String()
var givenName = String()
var familyName = String()

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.

// Use Firebase library to configure APIs
FIRApp.configure()

GIDSignIn.sharedInstance().clientID = FIRApp.defaultApp()?.options.clientID
GIDSignIn.sharedInstance().delegate = self

return true
}

func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {

return GIDSignIn.sharedInstance().handle(url,
sourceApplication: options[UIApplicationOpenURLOptionsKey.sourceApplication] as? String,
annotation: options[UIApplicationOpenURLOptionsKey.annotation])
}

func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {

if let error = error {
print(error.localizedDescription)
return
}
print("User signed into Google")

let authentication = user.authentication
let credential = FIRGoogleAuthProvider.credential(withIDToken: (authentication?.idToken)!,
accessToken: (authentication?.accessToken)!)

FIRAuth.auth()?.signIn(with: credential) { (user, error) in
print("User Signed Into Firebase")


self.databaseRef = FIRDatabase.database().reference()

self.databaseRef.child("user_profiles").child(user!.uid).observeSingleEvent(of: .value, with: { (snapshot) in

let snapshot = snapshot.value as? NSDictionary

if(snapshot == nil)
{
self.databaseRef.child("user_profiles").child(user!.uid).child("name").setValue(user?.displayName)
self.databaseRef.child("user_profiles").child(user!.uid).child("email").setValue(user?.email)
}


})

}

userID = user.userID
givenName = user.profile.givenName
familyName = user.profile.familyName


continueToWallet()
}


In the View Controller, I am calling the App delegate and trying to receive the data, but it gives me an error saying, "Instance member 'User ID' cannot be used on type 'AppDelegate'"

class addToWalletController: UIViewController {

var ID = String()

let delegate = UIApplication.shared.delegate as! AppDelegate
let user = AppDelegate.userID
let firstName = AppDelegate.givenName
let lastName = AppDelegate.familyName

override func viewDidLoad() {
super.viewDidLoad()
}

}


I have also tried switching AppDelegate with delegate in the =AppDelegate.userID but it gives me the same error. What's going on?

Answer Source

The error message have told you property initializers run before 'self' is available.

Maybe you should initialize it in viewDidLoad

let delegate = UIApplication.shared.delegate as! AppDelegate
var user: String?
var firstName: String?
var lastName: String?

override func viewDidLoad() {
    super.viewDidLoad()

    user = delegate.userID
    firstName = delegate.givenName
    lastName = delegate.familyName
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download