从View Controller中的App Delegate访问变量

时间:2017-03-01 03:12:53

标签: ios swift swift3

我正在我的应用上实施Google登录,我需要访问用户ID和姓/名。存储该数据的变量位于App Delegate中。我在内部和外部都在搜索互联网,寻找在Swift 3中如何做到这一点,而且绝对没有。

这是App代表(至少是重要的部分):

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

在View Controller中,我正在调用App委托并尝试接收数据,但它给出了一个错误,说“实例成员'用户ID'不能用于类型'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()
}

}

我也尝试在= AppDelegate.userID中使用委托切换AppDelegate,但它给了我同样的错误。发生了什么事?

5 个答案:

答案 0 :(得分:18)

错误消息已告诉您property initializers run before 'self' is available

也许你应该在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
}

答案 1 :(得分:7)

AppDelegate是班级。你想要的是AppDelegate的实例,它是你的应用程序的代理。此外,您不能使用您声明的delegate常量来设置其他实例成员的值,因为它本身也是一个实例成员。

我喜欢在AppDelegate中实现这样的功能:

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

然后我可以从其他地方这样称呼它:

let firstName = AppDelegate.shared().givenName

另一种选择是使用您定义的delegate属性设置这些属性的值,但稍后会在viewDidLoad中执行,例如Alvin的回答建议。< / p>

答案 2 :(得分:1)

更新:您无需为GoogleSignIn访问Appdelegate。在按钮操作中使用以下代码

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

答案 3 :(得分:0)

你也可以制作类似于UIApplication.shared的东西....比你必须将它添加到AppDelegates:

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

或类似的东西:

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

比你有Swift 3.x语法:)

干杯!

答案 4 :(得分:0)

您永远不要这样做。您应该具有适当的抽象来处理登录。应用程序委托应该是私有类。使用此共享状态有什么意义? Google登录使用便捷的方法来处理此问题,并且用户凭据不应该存储在应用程序委托中。您可以根据需要使用某些类或数据库。