Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Safari Services crash [SFAuthenticationViewController dismissViewControllerAnimated:completion:]

Tags:

ios

crash

ios11

I'm having a crash very often in my app. It seems a crash from iOS system only happening in the latest iOS 11.

This is the crash

Crashed: com.apple.main-thread
0  libobjc.A.dylib                0x18439d7ec objc_object::release() + 8
1  SafariServices                 0x1995d471c __75-[SFAuthenticationViewController dismissViewControllerAnimated:completion:]_block_invoke + 32
2  UIKit                          0x18e5bf030 -[UIPresentationController transitionDidFinish:] + 1320
3  UIKit                          0x18e79e760 -[_UICurrentContextPresentationController transitionDidFinish:] + 44
4  UIKit                          0x18e5c2a20 __56-[UIPresentationController runTransitionForCurrentState]_block_invoke_2 + 188
5  UIKit                          0x18e38e9d8 -[_UIViewControllerTransitionContext completeTransition:] + 116
6  UIKit                          0x18e38e7c8 -[UITransitionView notifyDidCompleteTransition:] + 252
7  UIKit                          0x18e38e260 -[UITransitionView _didCompleteTransition:] + 1128
8  UIKit                          0x18e38dde4 -[UITransitionView _transitionDidStop:finished:] + 120
9  UIKit                          0x18e2b370c -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 312
10 UIKit                          0x18e2b3418 -[UIViewAnimationState animationDidStop:finished:] + 296
11 UIKit                          0x18e2b34b8 -[UIViewAnimationState animationDidStop:finished:] + 456
12 QuartzCore                     0x188e57d6c CA::Layer::run_animation_callbacks(void*) + 284
13 libdispatch.dylib              0x1847f1048 _dispatch_client_callout + 16
14 libdispatch.dylib              0x1847fdb74 _dispatch_main_queue_callback_4CF$VARIANT$mp + 1016
15 CoreFoundation                 0x184e13f20 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
16 CoreFoundation                 0x184e11afc __CFRunLoopRun + 2012
17 CoreFoundation                 0x184d322d8 CFRunLoopRunSpecific + 436
18 GraphicsServices               0x186bc3f84 GSEventRunModal + 100
19 UIKit                          0x18e2df880 UIApplicationMain + 208
20 Jaumo                          0x1005674b4 main (main.m:20)
21 libdyld.dylib                  0x18485656c start + 4

Not sure what is this crash. anyone can help with this issue?

like image 774
Pablo Martinez Avatar asked Oct 29 '17 16:10

Pablo Martinez


2 Answers

We had the same issue after we updated to the latest Facebook SDK (from a quite old version 4.11 to 4.27.1). Actually we had some calls initiated from applicationDidBecomeActive event which triggered the Facebook login (so opening a SFAuthenticationSession which opens the SFAuthenticationViewController the prompt that asks the user to continue authentication with Facebook or other 3rd party). Once the user tapped on "Continue" it triggered the applicationDidBecomeActive event again. This caused an endless loop of starting new SFAuthenticaionSessions which resulted in a crash. So we decided not to call Facebook login from this event at all. To summarize how to avoid this crash: you have to make sure that you call Facebook login (or SFAuthenticationSession start() method) only once at the same time.

like image 99
Zoltán Homoki Avatar answered Oct 03 '22 23:10

Zoltán Homoki


As @Zoltán Homoki and @Jelly said, we should call logInWithReadPermissions only once.

For this purpose a common implementation (that was ok before) is to set a flag in the appDelegate like :

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
    if ([[url.scheme substringToIndex:2] isEqualToString:@"fb"]) {
        _fromFbConnect = YES; // <- This flag
        returnValue = [[FBSDKApplicationDelegate sharedInstance] application:application openURL:url sourceApplication:sourceApplication annotation:annotation];
    }
    // Manage app deep links here
}

Then use it to prevent multiple call to the Facebook login :

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    [FBSDKAppEvents activateApp];

    if (_fromFbConnect == NO) { // <- Always `YES` on iOS11 with FB SDK 4.27
        // Refresh the facebook token
        if ([FBSDKAccessToken currentAccessToken] != nil) {
            [[FBSDKLoginManager new] logInWithReadPermissions: // ...
        }
        _fromFbConnect = NO;
    }
}

The issue is that on iOS11 with FBSDKLoginKit >= 4.27 application:openURL:sourceApplication:annotation: is not called (nor application:openURL:option) so the flag is not set. That create multiple calls to the login (applicationDidBecomeActive being called when the user close the first popup)

The solution I found is to setup a flag before any call to FBSDKLoginManager and stop any other call until the process is done.

@property (assign, nonatomic) BOOL fbRequesting;

// ...

if(_fbRequesting == YES) {
    NSLog(@"Facebook login already in progress");
    return;
}

if ([FBSDKAccessToken currentAccessToken] != nil) {
    return;
}

_fbRequesting = YES;
[FBSDKProfile enableUpdatesOnAccessTokenChange:YES];

NSLog(@"Logging in to Facebook...");

@weakify(self);
[[FBSDKLoginManager new] logInWithReadPermissions:... fromViewController:... handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
    @strongify(self);

    // Handle login

    _fbRequesting = NO;
    })
];

This seems to work with versions 4.22 to 4.28 of FBSDKLoginKit.

like image 45
Axel Guilmin Avatar answered Oct 04 '22 01:10

Axel Guilmin