Несогласованный сбой при отправке в facebook с использованием FBNativeDialogs на iOS6.0
Я уже некоторое время борюсь с этой проблемой, и я просто не могу воспроизвести ее достаточно точно, чтобы описать конкретный вариант использования. По существу, то, что я делаю, выдает запрос на открытие родного диалогового окна общего доступа к iOS 6.0 Facebook (с использованием iOS SDK для Windows 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
ИЛИ Я не вижу сбоя, и появляется диалоговое окно с родным общим доступом.
Стек подразумевает вызов в потоке с именем UIRemoteViewControllerCreationRequest
в этом пункте, вот 2 примера для двух разных сбоев:
![enter image description here]()
![enter image description here]()
Спасибо за помощь
Ответы
Ответ 1
После большого количества экспериментов с моим приложением и изучения источника SDK в Facebook я понял три вещи:
-
Создание SLComposeViewController
самостоятельно не помогает. Facebook SDK довольно прост в этом, он просто создает контроллер точно так же, как код в ответе с бонусом.
-
Когда вы авторизуете сеанс FB, ваше приложение деактивируется один или несколько раз. Это вызвано появлением предупреждений о подтверждении.
-
UIRemoteViewController
- это фактически SLComposeViewController
, который запускается в другом процессе.
Что вызвало мою ошибку?
- Пользователь подтверждает разрешения FB
- Это вызывает
applicationDidBecomeActive:
- Он также вызывает обратный вызов FB для представления диалога.
- My
applicationDidBecomeActive:
что-то делал с пользовательским интерфейсом, что не должно было быть сделано, когда появлялись диалоговые окна FB (перезагрузка таблицы).
Кроме того, есть еще одна вещь, о которой нужно быть осторожностью - обработчик presentShareDialogModallyFrom...
не вызывается в каком-либо конкретном потоке (см. SLComposeViewController
docs). Это означает, что вы должны использовать dispatch_async(dispatch_get_main_queue(), ...)
из обработчика, если вы обновляете его.
EDIT:
Очевидно, что на предыдущих шагах были зафиксированы некоторые сбои, но одна из аварий не была решена. После многих поисковых запросов и поиска на форумах Apple Developer, я думаю, что в iOS 6 есть ошибка, связанная с удаленными контроллерами, и с помощью UIAppearance
, особенно внешний вид UINavigationBar
. В настоящее время я удаляю использование UIApperance
из своего приложения.
Ответ 2
Это очень странный способ опубликовать сообщение в 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
При необходимости здесь есть видео .
Ответ 3
Извините, некоторые из них довольно угадывают, но я думал, что попробую:
Вы уверены, что canPresentShareDialogWithSession безопасен для вызова из потока, отличного от UI?
У вас есть строка в обоих стеках _NSDictionaryEnumerate. Похоже, что из более высоких функций что-то вызывает enumerateKeysAndObjectsUsingBlock:.
Основываясь на вашей заметке о сбоях в работе сразу после [presentShareDialogModallyFrom: отправитель]. Есть ли что-то освобождающееся, когда вид отправителя исчезает?
Переменное "изображение" либо сохраняется, либо автореализовано в зависимости от того, какой путь кода он принял.
Ответ 4
Я думаю, что проблема в том, что Уолт уже сказал. В вашем коде что-то делается вне основного потока.
В журнале сбоев вы можете увидеть, что кто-то устанавливает внешний вид (UIAppearance) на некоторый элемент пользовательского интерфейса из потока, отличного от UI. Это проблема. Эта операция ДОЛЖНА выполняться ТОЛЬКО в потоке пользовательского интерфейса (main).
Ответ 5
Я считаю, что это связано с комбинацией методов UIAppearance и запуском UIRemoteViewController из фонового потока. У нас такая же проблема в нашем приложении. Я собираюсь изменить класс презентатора, чтобы представить все наши удаленные viewControllers из основного потока и посмотреть, поможет ли это.
В вашем случае, я думаю, что-то в SDK для Facebook представляет что-то из фонового потока.
Я обновлю после того, как подтвержу, что мое исправление работает.
Ответ 6
Это ошибка в iOS 6 и Social Framework, посмотрите здесь Внешний вид UINavigationBar и ошибка на Facebook-листах
Как это решить?
Вместо использования [UINavigationBar appearance]
используйте [UINavigationBar appearanceWhenContainedIn:...]
Вы можете использовать пользовательский класс для своего навигационного контроллера (например, CustomNavigationController), а затем применить его по внешнему виду:
[UINavigationBar appearanceWhenContainedIn:[CustomNavigationController class], nil]
Из моих экспериментов он должен использоваться для всех методов appearance
, а не только UINavigationBar
, но также UIBarButtonItem
и т.д. (на каждый отправляемый объект appearance
)
Ответ 7
Я думаю, что вы знаете, что очевидно, но однажды я встретил эту ошибку, и это был NSMutableArray, который был мутирован, будучи перечисляемым внутри оператора for..in.
Посмотрите на NSMutableArray, вы найдете свою ошибку.
Кстати, если вы нацеливаете ios6, почему бы вам не использовать социальную инфраструктуру с собственной реализацией facebook?