web-dev-qa-db-de.com

Greifen Sie auf Variablen von App Delegate in View Controller zu

Ich implementiere Google in meiner App und muss auf die Benutzer-ID und den Vor-/Nachnamen zugreifen. Die Variablen, die diese Daten speichern, befinden sich im App-Delegierten. Ich habe im Internet nach innen und außen gesucht und gesucht, wie dies in Swift 3 möglich ist, und es gibt absolut nichts.

Hier ist der App-Delegierte (zumindest der Teil, der zählt):

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()
}

Im View Controller rufe ich den App-Delegierten an und versuche, die Daten zu empfangen. Es wird jedoch die Fehlermeldung angezeigt, dass "Instanzmitglied" Benutzer-ID "nicht für Typ" AppDelegate "verwendet werden kann."

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()
}

}

Ich habe auch versucht, AppDelegate mit Delegat in der = AppDelegate.userID umzuschalten, aber es gibt den gleichen Fehler. Was ist los?

5

Die Fehlermeldung hat Ihnen property initializers run before 'self' is available mitgeteilt.

Vielleicht sollten Sie es in viewDidLoad initialisieren

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
}
17
AlvinZhu

AppDelegate ist die Klasse. Sie möchten die Instanz von AppDelegate, die der Delegat Ihrer Anwendung ist. Außerdem können Sie die von Ihnen deklarierte Konstante delegate nicht zum Festlegen der Werte anderer Instanzmitglieder verwenden, da sie auch selbst ein Instanzmitglied ist. 

Ich möchte eine Funktion in AppDelegate so implementieren:

static func shared() -> AppDelegate {
    return UIApplication.shared.delegate as! AppDelegate
}

Und dann kann ich es einfach anderswo nennen:

let firstName = AppDelegate.shared().givenName

Eine andere Option wäre, die Werte dieser Eigenschaften mithilfe der von Ihnen definierten delegate-Eigenschaft festzulegen, dies später jedoch wie in viewDidLoad zu tun, wie es in der Antwort von Alvin vorgeschlagen wird.

6
Samantha

Update: Sie müssen für GoogleSignIn nicht auf Appdelegate zugreifen. Verwenden Sie folgenden Code in Ihrer Schaltflächenaktion

 @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)
    }
}
1
phantom

Sie können auch etwas ähnliches wie UIApplication.shared machen.

open class var shared: AppDelegate {
    get {
        return UIApplication.shared.delegate as! AppDelegate
    }
}

oder sowas:

public class var shared: AppDelegate {
    return UIApplication.shared.delegate as! AppDelegate
}

Dann hast du die Swift 3.x-Syntax :)

Prost!

0
jLaszczewski

Sie sollten es niemals tun. Sie sollten über eine geeignete Abstraktion für die Anmeldung verfügen. Der App-Delegat sollte eine private Klasse sein. Was ist der Sinn dieses gemeinsam genutzten Zustands? Bei der Google-Anmeldung gibt es praktische Methoden, um dies zu behandeln, und Benutzeranmeldeinformationen sollten nicht im App-Delegierten gespeichert werden. Sie können bei Bedarf eine Klasse oder Datenbank verwenden.

0
Myrenkar