我正在我的应用上实施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,但它给了我同样的错误。发生了什么事?
答案 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登录使用便捷的方法来处理此问题,并且用户凭据不应该存储在应用程序委托中。您可以根据需要使用某些类或数据库。