尝试制作Google SignIn助手,但'uiDelegate必须是| UIViewController |

时间:2018-11-03 19:38:46

标签: swift google-signin

我试图使Google社交帮助器成为ViewController之外的NSObject。我目前在根ViewController中使用UIApplication扩展名登录,但是仍然出现错误。

  

'uiDelegate必须是| UIViewController |。或实现| signIn:presentViewController:|和| signIn:dismissViewController:| | GIDSignInUIDelegate |中的方法。”

这是我的社会帮助对象

import GoogleSignIn

class GidHelper: NSObject, GIDSignInUIDelegate, GIDSignInDelegate {

private let succesAuth: (String, String, String, String) -> ()
private let failedAuth: (Error) -> ()

init(succesAuth: @escaping (String, String, String, String) -> (), failedAuth: @escaping (Error) -> ()) {
    self.succesAuth = succesAuth
    self.failedAuth = failedAuth
    super.init()
    GIDSignIn.sharedInstance().uiDelegate = self
    GIDSignIn.sharedInstance().delegate = self
}

func openGidAuthorization() {
    GIDSignIn.sharedInstance().signIn()
}

func gidLogout() {
    GIDSignIn.sharedInstance().signOut()
}

// Present a view that prompts the user to sign in with Google
private func signIn(signIn: GIDSignIn!,
                    presentViewController viewController: UIViewController!) {
    UIApplication.topViewController()?.present(viewController, animated: true, completion: nil)
}

private func signIn(signIn: GIDSignIn!,
                    dismissViewController viewController: UIViewController!) {
    UIApplication.topViewController()?.dismiss(animated: true, completion: nil)
}

func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
    if let error = error {
        print("\(error.localizedDescription)")
        self.failedAuth(error)
    } else {
        let userId = user.userID
        let accessToken = user.authentication.accessToken 
        let userAvatarUrl = user.profile.imageURL(withDimension: 100)?.absoluteString
        let email = user.profile.email
        self.succesAuth(accessToken!, userId!, email!, userAvatarUrl!)
    }
}
}

我的UIApplication扩展名:

  import Foundation
  import UIKit

  extension UIApplication {
        class func topViewController(controller: UIViewController? = 
  UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
        if let navigationController = controller as? UINavigationController {
            return topViewController(controller: navigationController.visibleViewController)
        }
        if let tabController = controller as? UITabBarController {
            if let selected = tabController.selectedViewController {
                return topViewController(controller: selected)
            }
        }
        if let presented = controller?.presentedViewController {
            return topViewController(controller: presented)
        }
        return controller
    }
}

1 个答案:

答案 0 :(得分:-1)

您的GidHelper类的实现从初始化开始到此扩展名看起来很奇怪:(。我建议您创建一个服务(让它成为您的GoogleLoginService),使其成为单例并创建一个NavigationService而不是带有扩展名的杂物。这是一些实现方法的想法:

import GoogleSignIn
final class GoogleLoginService: NSObject {

typealias SignInResponse = (_ user: User?, _ error: Error?) -> ()

static let sharedInstance = GoogleLoginService()
private var presenter: UIViewController?
private var singInCompletion: SignInResponse?

//Call next function in appDelegate: didFinishLaunchingWithOptions
@discardableResult func registerInApplication(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    if let url = Bundle.main.url(forResource: "GoogleService-Info", withExtension: "plist"),
        let data = try? Data(contentsOf: url) {
        let dictionary = try? PropertyListSerialization.propertyList(from: data, options: [], format: nil) as? [String : AnyObject]
        if let clientID = dictionary??["CLIENT_ID"] {
            GIDSignIn.sharedInstance().clientID = clientID as? String
        }
    }
    GIDSignIn.sharedInstance().delegate = self
    GIDSignIn.sharedInstance().uiDelegate = self
    return true
}

// Call this function in AppDelegate: open url
@discardableResult func handleURLIn(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool {
    return GIDSignIn.sharedInstance().handle(url, sourceApplication: options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String, annotation: options[UIApplication.OpenURLOptionsKey.annotation])
}

// MARK: - UserManagement

func signIn(_ controller: UIViewController, completion: SignInResponse?) {
    singInCompletion = completion
    presenter = controller
    GIDSignIn.sharedInstance().signIn()
}

func signOut() {
    GIDSignIn.sharedInstance().signOut()
}

func isLoggedIn() -> Bool {
    return GIDSignIn.sharedInstance().hasAuthInKeychain()
}
}

extension GoogleLoginService: GIDSignInDelegate {

// MARK: - GIDSignInDelegate

    func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
            if let error = error {
                self.singInCompletion?(nil, error)
                return
            }
            guard let authentication = user.authentication else {
                self.singInCompletion?(nil, error)
                return
            }
            let googleUserObj = User(name: user.profile.name) // <-- You can get your user data 
        }
    }

extension GoogleLoginService: GIDSignInUIDelegate {

    // MARK: - GIDSignInUIDelegate

    func sign(_ signIn: GIDSignIn!, present viewController: UIViewController!) {
        presenter?.present(viewController, animated: true, completion: nil)
    }

    func sign(_ signIn: GIDSignIn!, dismiss viewController: UIViewController!) {
        presenter = nil
        viewController.dismiss(animated: true, completion: nil)
    }
}

现在,您可以使用isLoggedIn方法将结果保存为UserDefaults,并使用NavigationService检查用户是否登录并转到适当的视图控制器(例如,查看以下{ {1}}:

NavigavionService

希望它可以帮助您重构代码并避免出现此错误:)祝您好运!