Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why this callback doesn't gets called unless I assign the result of this function to a class variable

Tags:

ios

swift

I have this function that is from the AppAuth examples, I realised that in iOS13 I don't really need to store the return value for the OIDAuthState.authState, so I tried to clean up the code by removing the appDelegate.currentAuthorizationFlow =, but once I remove that, the callback doesn't gets called anymore. And this currentAuthorizationFlow is not used anywhere else in the code.

I have also tried assigning the result of OIDAuthState.authState to a function local variable, where the call back also will not be called.

If I assign the results of OIDAuthState.authState to a class member variable in the current class, then the call back will be called.

Why is the behaviour as such? It seems very baffling to me.

func signInGmail() {
    let redirectURI = URL(string: gmail_kRedirectURI)!
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    
    let config = GTMAppAuthFetcherAuthorization.configurationForGoogle()
    let scopes = [OIDScopeOpenID, OIDScopeProfile, OIDScopeEmail, kGTLRAuthScopeGmailReadonly]
    
    let request = OIDAuthorizationRequest.init(configuration: config, clientId: gmail_kClientID, scopes: scopes, redirectURL: redirectURI, responseType: OIDResponseTypeCode, additionalParameters: nil)
    
    appDelegate.currentAuthorizationFlow = OIDAuthState.authState(byPresenting: request, presenting: self, callback: { (authState, error) in
        //handleError
        
        if let authState = authState {
            let authorizer = GTMAppAuthFetcherAuthorization(authState: authState)
            
            self.pickGmailLabels(authorizer: authorizer)
        }
    })
}
like image 438
Phuah Yee Keat Avatar asked Oct 17 '20 03:10

Phuah Yee Keat


Video Answer


1 Answers

Here's what the documentation says about the return value of authState(byPresenting:presenting:callback:)

Returns A OIDExternalUserAgentSession instance which will terminate when it receives a cancel (OIDExternalUserAgentSession-p) message, or after processing a resumeExternalUserAgentFlowWithURL: (OIDExternalUserAgentSession-p) message.

What might happen here is that either the dealloc for the returned session calls cancel, or the session along with the callback get deallocated if no one retains them. And since you no longer store a reference to it when you remove the assignment, the session might get discarded right away. However the need to retain the session is not explicitly stated into the documentation, so if this is the root cause of the problem, either the documentation is laking this piece of information, or there's a bug in the implementation.

Note that it's not an unusual pattern having to hold on some async task identifier to make sure the whole operation completes, however this should be stated into the documentation, if this is the intended behaviour.

like image 145
Cristik Avatar answered Oct 07 '22 21:10

Cristik