Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inconsistent crash while posting to facebook using FBNativeDialogs on iOS6.0

I've been struggling with this issue for a while now and I just can't seem to reproduce it accurately enough to describe the exact use-case. Essentially, what I'm doing is issuing a request for opening a native iOS 6.0 Facebook share dialog (using the Facebook iOS SDK 3.1.1):

if ([[SocialManager sharedManager] isNativeFacebookShareDialogAvailable]) {

        if (!url) {
            url = [NSURL URLWithString:@""];
        }

        if (!imageUrl) {
            imageUrl = [NSURL URLWithString:@""];
        }

        dispatch_async(backgroundQueue, ^{

            NSData *imageData  = [NSData dataWithContentsOfURL:imageUrl];
            UIImage *image     = [UIImage imageWithData:imageData];

            if (!image) {
                image = [[UIImage alloc] init];
            }

            if ([FBNativeDialogs canPresentShareDialogWithSession:[FBSession activeSession]]) {

                dispatch_async(dispatch_get_main_queue(), ^{
                    [FBNativeDialogs presentShareDialogModallyFrom:sender initialText:initialText images:@[image] urls:@[url] handler:^(FBNativeDialogResult result, NSError *error) {
                        if (error) {
                            failBlock([[error userInfo] description]);
                        } else {
                            if (result == FBNativeDialogResultSucceeded) {
                                completionBlock();
                            } else if (result == FBNativeDialogResultCancelled) {
                                failBlock(@"User cancelled");
                            } else if (result == FBNativeDialogResultError) {
                                failBlock(@"Unknown error");
                            }
                        }
                    }];
                });

            } else {
                LogErr(@"Can't display native share dialog for active session");
            }
        });
    }

Right after presentShareDialogModallyFrom:sender is called, I either get the following crash log:

*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSArrayM: 0x1d161490> was mutated while being enumerated.'
*** First throw call stack:
(0x32ede2a3 0x326b097f 0x32eddd85 0x35da094d 0x32edb62f 0x35da07f5 0x35e7e5e5 0x35e0ccd7 0x35e0cb6d 0x372c490f 0x35e0ca61 0x35e160d5 0x372b783b 0x35e160b1 0x372b711f 0x372b699b 0x372b6895 0x372c5215 0x372c53b9 0x36f5fa11 0x36f5f8a4)
libc++abi.dylib: terminate called throwing an exception

OR I get no crash and the native share dialog appears as it should.

The stack implies a call on a thread called UIRemoteViewControllerCreationRequest at this point, here are 2 examples for two different crashes: enter image description hereenter image description here

Thanks for your help

like image 461
Stavash Avatar asked Feb 12 '13 10:02

Stavash


1 Answers

After a lot of experimenting with my application and looking into Facebook SDK source I realized 3 things:

  1. Creating a SLComposeViewController by yourself doesn't help. Facebook SDK is pretty simple in this, it just creates the controller exactly like the code in the answer with bonus.

  2. When you are authorizing the FB session, your application is deactivated once or more times. This is caused by the permission confirmation alerts appearing.

  3. The UIRemoteViewController is actually the SLComposeViewController which is run in a different process.

What caused my error?

  1. User confirms FB permissions
  2. This triggers applicationDidBecomeActive:
  3. It also triggers FB callback to present the dialog.
  4. My applicationDidBecomeActive: was doing something with the UI what was not supposed to be done when the FB dialogs were appearing (tirggering a table reload).

Also, there is another thing to be careful of - the handler of presentShareDialogModallyFrom... is not called on any particular thread (see SLComposeViewController docs). That means that you should use dispatch_async(dispatch_get_main_queue(), ...) from the handler if you are updating UI from it.

EDIT: Obviously, the previous steps fixed some crashes but one of the crashes was not solved. After a lot of googling and searching Apple Developer forums, I think there is a bug in iOS 6 connected with Remote Controllers and using UIAppearance, especially the appearance of UINavigationBar. I am currently removing the use of UIApperance from my app.

like image 117
Sulthan Avatar answered Sep 23 '22 10:09

Sulthan