我试图使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
}
}
答案 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
希望它可以帮助您重构代码并避免出现此错误:)祝您好运!