GTMAppAuth icon indicating copy to clipboard operation
GTMAppAuth copied to clipboard

Terminating app due to uncaught exception 'Attempt to call unavailable initializer.', reason: 'Called: init Designated Initializer:initWithAuthState:'

Open ibhavin opened this issue 8 years ago • 3 comments

I am using google drive sdk and I have implemented GTMAppAuth for login in my swift project.

In AppDelegate.swift:

weak var currentAuthorizationFlow: OIDAuthorizationFlowSession?
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
        if (currentAuthorizationFlow?.resumeAuthorizationFlow(with: url))! {
            currentAuthorizationFlow = nil
            return true
        }
        // Your additional URL handling (if any) goes here.
        return false
    }

In ViewController.swift:

//MARK:- Login Tapped
    @IBAction func login_Tapped(_ sender: RBButton) {
        let issuer = URL.init(string: kIssuer)
        let redirectUrl = URL.init(string: kRedirectURI)
        
        OIDAuthorizationService.discoverConfiguration(forIssuer: issuer!) { (configuration, error) in
            if !(configuration != nil) {
                print("Error retrieving discovery document: \(error?.localizedDescription)")
                //self.setGTMAuthorization(authorization: nil)
                return
            }
            print("Got Configuration: \(configuration)")
            
            //authentication request
            let request = OIDAuthorizationRequest.init(configuration: configuration!, clientId: kClientID, scopes: [OIDScopeOpenID, OIDScopeProfile], redirectURL: redirectUrl!, responseType: OIDResponseTypeCode, additionalParameters: nil)
            
            let appDelegate = UIApplication.shared.delegate as! AppDelegate
            print("Initiating authorization request with scope: \(request.scope)")
            
            appDelegate.currentAuthorizationFlow = OIDAuthState.authState(byPresenting: request, presenting: self, callback: { (authState, error) in
                if (authState != nil) {
                    let authorization = GTMAppAuthFetcherAuthorization.init(authState: authState!)
                    self.setGTMAuthorization(authorization: authorization)
                    print("Got authorization access token: \(authState?.lastTokenResponse?.accessToken)")
                } else {
                    //self.setGTMAuthorization(authorization: nil)
                    print("Authorization error: \(error?.localizedDescription)")
                }
            })
        }
    }
    
    func setGTMAuthorization(authorization: GTMAppAuthFetcherAuthorization) {
        if appAuthorization.isEqual(authorization) {
            return
        }
        appAuthorization = authorization
        self.stateChanged()
    }
    
    func stateChanged() {
        self.saveState()
        self.updateUI()
    }
    
    func saveState() {
        if appAuthorization.canAuthorize() {
            GTMAppAuthFetcherAuthorization.save(appAuthorization, toKeychainForName: kExampleAuthorizerKey)
        } else {
            GTMAppAuthFetcherAuthorization.removeFromKeychain(forName: kExampleAuthorizerKey)
        }
    }

But app is crashing(as title says) while view load. BTW my viewDidLoad() is empty.

I have put exception breakpoint and it stops here: GTM_UNAVAILABLE_USE_INITIALIZER(@selector(initWithAuthState:));

Please help regarding this issue.

ibhavin avatar Apr 07 '17 06:04 ibhavin

I think: let authorization = GTMAppAuthFetcherAuthorization.init(authState: authState!)

Should be: let authorization = GTMAppAuthFetcherAuthorization. initWithAuthState(authState: authState!)

That exception is thrown when the default initializer is called.

WilliamDenniss avatar Jun 01 '17 04:06 WilliamDenniss

I managed to get it working with my sample project for Swift/ macOs - if this is still an issue- then please see the code there. I think its down to how you handle your URL pickup.

Pull request is #60

grantkemp avatar Feb 23 '18 20:02 grantkemp

This issue should track the fact that because of the way the initializers are declared, Swift does not know that GTMAppAuthFetcherAuthorization.init() is an invalid initializer. So you can compile code that will always crash. That's not right, it should be marked as unavailable to swift or whatever pragma you like, in order that GTMAppAuthFetcherAuthorization.init() does not compile.

xaphod avatar Feb 20 '19 18:02 xaphod