在iOS6.0上使用FBNativeDialogs发布到Facebook时发生不一致的崩溃

时间:2013-02-12 10:56:49

标签: ios objective-c facebook-ios-sdk fbnativedialogs

我一直在努力解决这个问题一段时间,我似乎无法准确地再现它以描述确切的用例。基本上,我正在做的是发出打开原生iOS 6.0 Facebook共享对话框的请求(使用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");
            }
        });
    }

在调用presentShareDialogModallyFrom:sender之后,我得到以下崩溃日志:

*** 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 我没有崩溃,原生共享对话框应该出现。

此时栈意味着对名为UIRemoteViewControllerCreationRequest的线程进行调用,以下是两次不同崩溃的2个示例: enter image description here enter image description here

感谢您的帮助

7 个答案:

答案 0 :(得分:2)

在对我的应用程序进行了大量实验并查看Facebook SDK源代码后,我意识到了三件事:

  1. 自己创建SLComposeViewController无济于事。 Facebook SDK非常简单,它只是创建控制器,就像答案中的代码一样。

  2. 当您授权FB会话时,您的应用程序将被停用一次或多次。这是由出现权限确认警报引起的。

  3. UIRemoteViewController实际上是SLComposeViewController,它在不同的流程中运行。

  4. 导致我错误的原因是什么?

    1. 用户确认FB权限
    2. 这会触发applicationDidBecomeActive:
    3. 它还会触发FB回调以显示对话框。
    4. 我的applicationDidBecomeActive:正在使用UI做一些事情,当FB对话框出现时不应该这样做(tirggering table reload)。
    5. 另外,还有一点要注意 - presentShareDialogModallyFrom...的处理程序不会在任何特定线程上调用(请参阅SLComposeViewController docs)。这意味着如果要从中更新UI,则应该使用处理程序中的dispatch_async(dispatch_get_main_queue(), ...)

      编辑: 显然,前面的步骤修复了一些崩溃但其中一个崩溃没有解决。经过大量谷歌搜索和搜索Apple Developer论坛后,我认为iOS 6中存在与远程控制器连接并使用UIAppearance的错误,尤其是UINavigationBar的外观。我目前正在从我的应用中删除使用UIApperance

答案 1 :(得分:1)

将帖子发布到Facebook是一种非常奇怪的方式。这是一种永远不会崩溃的简单方法。

ViewController.h

#import <UIKit/UIKit.h>
#import <Social/Social.h>
#import <Accounts/Accounts.h>

@interface ViewController : UIViewController {
SLComposeViewController *mySLComposerSheet;
}
- (IBAction)PostToFacebook:(id)sender;

@end

ViewController.m @implementation ViewController

- (IBAction)PostToFacebook:(id)sender {
mySLComposerSheet = [[SLComposeViewController alloc] init];
mySLComposerSheet = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
[mySLComposerSheet setInitialText:@"Place Text Here"];
[self presentViewController:mySLComposerSheet animated:YES completion:nil];
}
@end

如果需要,可以观看视频here.

答案 2 :(得分:1)

抱歉,其中一些是猜测,但我想我会尝试:

您确定canPresentShareDialogWithSession可以安全地从非UI线程调用吗?

在_NSDictionaryEnumerate的两个堆栈中都有一行。它看起来像是从更高级的函数,调用enumerateKeysAndObjectsUsingBlock:。

基于您在[presentShareDialogModallyFrom:sender]之后崩溃的事情。当发件人的观点消失时,是否有某些东西被释放?

根据所采用的代码路径,保留或自动释放变量“image”。

答案 3 :(得分:1)

我认为问题是沃尔特已经说过的。在你的代码中,有些东西是在主线程之外完成的。

在崩溃日志中,您可以看到有人正在从非UI线程的某些UI元素上设置外观(UIAppearance)。那就是问题所在。此操作必须仅在UI(主)线程中完成。

答案 4 :(得分:1)

我认为这与UIAppearance方法的组合以及从后台线程启动UIRemoteViewController有关。我们的应用中遇到了同样的问题。我将更改我们的演示者类,以显示主线程中的所有远程viewControllers,看看是否有帮助。

在您的情况下,我猜Facebook SDK中的某些东西是从后台线程中呈现的东西。

在我确认我的修复程序有效后,我会更新。

答案 5 :(得分:1)

这是iOS 6和社交框架中的错误,请在此处查看答案UINavigationBar appearance and Facebook-Sheet Bug

如何解决这个问题?

只需使用[UINavigationBar appearance] [UINavigationBar appearanceWhenContainedIn:...]

即可

您可以为导航控制器使用自定义类(例如CustomNavigationController),然后将其应用于外观:

[UINavigationBar appearanceWhenContainedIn:[CustomNavigationController class], nil]

从我的实验中,它应该用于所有appearance方法,不仅UINavigationBar而且UIBarButtonItem等。(在您发送appearance消息的每个对象上)< / p>

答案 6 :(得分:-2)

我认为你知道什么是显而易见的,但我遇到过这个错误,它是一个NSMutableArray,在for..in语句中枚举时发生了变异。

看看NSMutableArray,你会发现你的错误。

顺便说一句,如果您定位ios6,为什么不使用本机Facebook实现的社交框架?