谷歌登录崩溃和错误:uiDelegate必须是|UIViewController|。

4

我正在尝试将Google登录功能实现到iOS应用程序中,但是当单击“登录”按钮时,应用程序会崩溃,并显示以下错误:

reason: 'uiDelegate must either be a |UIViewController| or implement the |signIn:presentViewController:| and |signIn:dismissViewController:| methods from |GIDSignInUIDelegate|.'

我不确定我的问题出在哪里。我已经完全按照Google iOS github上的示例代码进行了操作。我也无法编译Google的示例。如果有人能指点我正确的方向,那就太好了。大部分的SO问题都基于过时的代码。
视图控制器
import UIKit
import GoogleSignIn

@objc(ViewController)

class ViewController: UIViewController, GIDSignInUIDelegate {

    // Viewcontroller buttons
    @IBOutlet weak var signInButton: GIDSignInButton!
    @IBOutlet weak var signOutButton: UIButton!
    @IBOutlet weak var disconnectButton: UIButton!
    @IBOutlet weak var statusText: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

        GIDSignIn.sharedInstance().uiDelegate = self

        // Sign in automatically
        GIDSignIn.sharedInstance().signInSilently()

        // Something to do with notifications
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(ViewController.receiveToggleAuthUINotification(_:)),
                                               name: NSNotification.Name(rawValue: "ToggleAuthUINotification"),
                                               object: nil)

        statusText.text = "Initialized Swift App..."
        toggleAuthUi()
    }

    // Sign out tapped
    @IBAction func didTapDisconnect(_ sender: AnyObject) {
        GIDSignIn.sharedInstance().disconnect()
        statusText.text = "Disconnecting"
    }

    // Toggle auth
    func toggleAuthUi() {
        if GIDSignIn.sharedInstance().hasAuthInKeychain() {
            signInButton.isHidden = true
            signOutButton.isHidden = false
            disconnectButton.isHidden = false
        } else {
            signInButton.isHidden = false
            signOutButton.isHidden = true
            disconnectButton.isHidden = true
        }
    }

    override var preferredStatusBarStyle: UIStatusBarStyle {
        return UIStatusBarStyle.lightContent
    }

    deinit {
        NotificationCenter.default.removeObserver(self,
                                                  name: NSNotification.Name(rawValue: "ToggleAuthUINotification"),
                                                  object: nil)
    }

    @objc func receiveToggleAuthUINotification(_ notification: NSNotification) {
        if notification.name.rawValue == "ToggleAuthUINotification" {
            self.toggleAuthUi()
            if notification.userInfo != nil {
                guard let userInfo = notification.userInfo as? [String:String] else {return}
                self.statusText.text = userInfo["statusText"]!
            }
        }
    }
}

应用代理:

import UIKit
import GoogleSignIn

@UIApplicationMain

class AppDelegate: UIResponder, UIApplicationDelegate, GIDSignInDelegate {

    var window: UIWindow?

    // Did Finished Launching
    func application (_ application: UIApplication,
                      didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

        // Init Sign in
        GIDSignIn.sharedInstance().clientID = "XXXXXXXXX"
        GIDSignIn.sharedInstance().delegate = self

        return true
    }

    // Open URL
    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])
    }

    public func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
        if let error = error {
            print("\(error.localizedDescription)")
            NotificationCenter.default.post(
                name: Notification.Name(rawValue: "ToggleAuthUINotificiation"), object: nil, userInfo: nil)
        } else {
            // User Stuff
            let userID = user.userID
            let idToken = user.authentication.idToken
            let fullName = user.profile.name
            let givenName = user.profile.givenName
            let familyName = user.profile.familyName
            let email = user.profile.email

            NotificationCenter.default.post(
                name: Notification.Name(rawValue: "ToggleAuthUINotification"),
                object: nil,
                userInfo: ["statusText": "Signed in user:\n\(fullName)"])
        }
    }

    public func sign(_ signIn: GIDSignIn!, didDisconnectWith user: GIDGoogleUser!, withError error: Error!) {
        // Disconnect the user
        NotificationCenter.default.post(
            name: Notification.Name(rawValue: "ToggleAuthUINotification"),
            object: nil,
            userInfo: ["statusText": "User has disconnect."])
    }

}

有什么解决方案吗? - Dia
很遗憾,我从未成功解决它。 - Rhys Edwards
以下由Nicolay提供的答案是正确的。您需要在呈现自定义登录按钮的视图控制器中实现GIDSignInUIDelegate及其委托方法,以进行Google登录。 - Ahmed Khedr
1个回答

1
如果使用非UIViewController作为uiDelegate,请检查Xcode是否警告您“Instance method [...] nearly matches optional requirement [...]”,并使用Fix-Its。确保您的函数与所需的签名完全匹配。
我按照示例代码操作后出现了相同的错误。
在我的情况下,设置有点不同,所以我不确定我的解决方案是否适用于你的问题 - 但是因为这个StackOverflow答案出现在谷歌搜索中,我想在这里提供我的解决方案给任何遇到此问题的人:
我需要一个非UIVIewController子类作为Google登录uiDelegate。如文档和错误所述,这意味着您需要实现一些方法。我已经实现了它们,所以很奇怪为什么事情会崩溃。
在我的情况下,问题在于从Google文档中复制的代码与Swift函数签名并不完全匹配。实际上,我在Xcode中收到警告,说“Instance method [...] nearly matches optional requirement [...]”。我使用了Xcode的自动修复功能(例如,将Error更改为NSError,或在函数参数前加上_等)。
然后一切都正常了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接