[Bug][TwitterKit][iOS] - Completion handler is being called too early

behaviors
issues
ios

#1

Hello,

When using the following method [[Twitter sharedInstance] logInWithCompletion… a view controller with an in-app webview is presented for the user to sign in, given the user does not have the native Twitter app nor has signed into Twitter via device’s Settings. Upon successful login, the completion handler is immediately called, without waiting for the modally presented view controller to finish its’ dismissal animation.

This can be a problem because a common pattern in apps will use the top most presented view controller in the key window to present their next view controller (in my case a TWTRShareEmailViewController to fetch user’s email). The dismissing view controller, however, is still seen as the top most presented view controller because it has not yet finished dismissing, and will not actually be available for presenting my next view controller (TWTRShareEmailViewController).

Tested on iOS 8.x


[Bug][TwitterKit][iOS] - SFSafariViewController login dismisses my view controller
#2

Hey @troystump,

Thanks for reaching out on this. Which version of TwitterKit are you using? I haven’t been able to reproduce this locally, so getting the version of the kit you’re using and some sample code to repro this would be great.

-Mike


#3

Hey there @bonnel,

Thanks for your reply. Allow me to be more clear, given the following sample code snippet:

 [[Twitter sharedInstance] logInWithCompletion:^(TWTRSession * _Nullable session, NSError * _Nullable error) {
            if (!error) {
                if (session) {
                    TWTRAPIClient *client = [[TWTRAPIClient alloc] initWithUserID:session.userID];
                    
                    
                    [client loadUserWithID:client.userID completion:^(TWTRUser * _Nullable user, NSError * _Nullable error) {
    .
    .
    .

The completion handler for - [TWTRAPIClient loadUserWithID…] will then attempt to fetch the user’s email by presenting an instance of TWTRShareEmailViewController.

So, the issue is either the completion handler from [[Twitter sharedInstance] logInWithCompletion…] or [TWTRAPIClient loadUserWithID…] is called before the dismissal animation completes for the view controller(s) that were previously presented internally by TwitterKit after a user logs in via a web view.

I am using TwitterKit v1.12.1


#4

Thanks @troystump, I chatted with a few of our iOS engineers about this and here is what’s going on.

The user objects are cached which is why the callback is being called immediately. The callback is not intended to be called when the view controller dismissed, but when the user actually logs in. In this case, you may need to restructure the code to not rely on the callback happening at a later time.

However, we will look into support this case in the future.

-Mike


#5

Hi @bonnell,

Could you provide a code sample of the recommended approach by the iOS engineers which logs the user in AND then fetches the user’s email, without running into the issue I’ve stated above?

I am not really sure I understand… The issue is occurring after successful log in of the user, when attempting to fetch a user’s email address fails to present the email TWTRShareEmailViewController. The authorization view controller(s) have not finished dismissing…


#6

Does the code here help?


#7

Unfortunately, that is exactly what I am doing after logging in the user… here is a more complete code snippet to showcase the issue:

[[Twitter sharedInstance] logInWithCompletion:^(TWTRSession * _Nullable session, NSError * _Nullable error) {
    if (!error) {
        if (session) {
            TWTRAPIClient *client = [[TWTRAPIClient alloc] initWithUserID:session.userID];
            
            
            [client loadUserWithID:client.userID completion:^(TWTRUser * _Nullable user, NSError * _Nullable error) {
                if (!error) {
                    if (user) {
                        TWTRSession *currentAccessSession = [[Twitter sharedInstance].sessionStore session];
                        
                        
                        if (currentAccessSession) {
                            UIViewController *viewControllerToPresentFrom = [UIViewController topMostPresentedViewControllerOfKeyWindow];
                            
                            
                            if (viewControllerToPresentFrom) {
                                TWTRShareEmailViewController *shareEmailViewController = [[TWTRShareEmailViewController alloc] initWithCompletion:^(NSString *email, NSError *error) {
                                    .
                                    .
                                    .
                                }];
                                // Cannot present because viewControllerToPresentFrom is a dismissing authorization view controller from TwitterKit after successful login...
                                [viewControllerToPresentFrom presentViewController:shareEmailViewController animated:YES completion:nil];
                            }
                        }
                    }
                }
            }];
        }
    }        
}];

[Bug][TwitterKit][iOS] - SFSafariViewController login dismisses my view controller
#8

@bonnell

Any update based on the above code sample?


#9

Hey @troystump,

Not yet, but I’m working on some additional sample code. Essentially, you need to handle the expectation that the user is already logged in and not ask for the email address quite so fast.

-Mike


#10

I’ve got the same behaviour as troystump… so any update on how to handle this properly would be helpful (especially a code sample).


#11

I’m having the same issue. Will update if I find a work around, as being unable to present the email view controller after a user logs in to Twitter really disrupts sign-up flow


#12

Update: worked around by using dispatch_async in the view controller that I am using to present the email VC. dispatch_async(dispatch_get_main_queue(), ^{
[myViewController presentViewController:shareEmailViewController animated:YES completion:nil];
});

It still isn’t perfect because there’s a moment where myViewController is visible before the Email shows up, so it would be nice to know when the TwitterKit VC is dismissed.


#13