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?
Start a segue from any object that implements an action method, such as a control or gesture recognizer. You may also start segues from table rows and collection view cells. Right-click the control or object in your current view controller. Drag the cursor to the view controller you want to present.
AppDelegate
is the class. What you want is the instance of AppDelegate
that is your application's delegate. In addition, you can't use the delegate
constant you've declared to set the values of other instance members because it is also an instance member itself.
I like to implement a function in AppDelegate
like this:
static func shared() -> AppDelegate {
return UIApplication.shared.delegate as! AppDelegate
}
And then I can just call it from elsewhere like so:
let firstName = AppDelegate.shared().givenName
Another option would be to set the values of these properties using the delegate
property you have defined, but do it later such as in viewDidLoad
, such as Alvin's answer suggests.
You can also made something similar to UIApplication.shared.... Than you have to add this to AppDelegates:
open class var shared: AppDelegate {
get {
return UIApplication.shared.delegate as! AppDelegate
}
}
or something like this:
public class var shared: AppDelegate {
return UIApplication.shared.delegate as! AppDelegate
}
Than you have Swift 3.x syntax :)
Cheers!
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
}
Update: You don't need to access Appdelegate for GoogleSignIn. Use following code in your button action
@IBAction func loginWithGoogle(_ sender: Any) {
GIDSignIn.sharedInstance().uiDelegate = self
GIDSignIn.sharedInstance().signIn()
//Be sure that you are signed-in
if(GIDSignIn.sharedInstance().hasAuthInKeychain()){
print("Signed-in")
//Use currentUser attribute.
print(GIDSignIn.sharedInstance().currentUser.profile.email)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With