NSMutableAttributedString initWithData: вызывая EXC_BAD_ACCESS при вращении
Я отображаю различные типы содержимого в tableview
и рассчитать высоту каждой ячейки, используя различные пользовательские методы, в heightForRowAtIndexPath
,
Один из этих пользовательских методов подразумевает преобразование некоторого HTML в NSMutableAttributedString
, а затем рассчитать высоту этого NSMutableAttributedString
,
Для преобразования HTML я использую новый initWithData:
метод.
Все работает отлично, за исключением случаев, когда я поворачиваю экран => Я каждый раз получаю exc_bad_access.
Используя инструменты / зомби, я смог найти ошибку, и на самом деле это initWithData:
,
(Когда я удаляю этот метод и создаю "простой" NSMutableAttributedString
с initWithString
Я могу менять ориентацию столько раз, сколько захочу, нет crash
больше).
Есть идеи почему?
(Кстати, мой проект использует ARC)
Скриншот инструмента / зомби:
Пользовательский метод вызывается в heightForRowAtIndexPath
:
+(CGFloat)heightForFacebookAttributedText:(NSString *)attributedText withWidth:(CGFloat)width
{
NSAttributedString *formatedText = [self formatRawFacebookContentForFrontEndRichTextContents:attributedText];
CGRect rect= [formatedText boundingRectWithSize:CGSizeMake(width, 1000) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading context:nil];
return ceilf(rect.size.height);
}
Пользовательский метод, использующий initWithData для HTML для NSMutableAttributedString
преобразование:
+(NSAttributedString *)formatRawFacebookContentForFrontEndRichTextContents:(NSString *)stringToFormat
{
// THIS GENERATE EXC_BAD_ACCESS ON DEVICE ROTATION (WORKS IF NO ROTATION)
NSData *dataContent = [stringToFormat dataUsingEncoding:NSUTF8StringEncoding];
NSMutableAttributedString *richTxtContent = [[NSMutableAttributedString alloc] initWithData:dataContent options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,NSCharacterEncodingDocumentAttribute: [NSNumber numberWithInt:NSUTF8StringEncoding]} documentAttributes:nil error:nil];
NSRange myRange;
myRange.location = 0;
myRange.length = richTxtContent.length;
[richTxtContent addAttributes:[self commonAttributesForFrontEndRichText] range:myRange];
return richTxtContent;
}
Если я заменил initWithData на простой initWithString, больше не будет exc_bad_access
+(NSAttributedString *)formatRawFacebookContentForFrontEndRichTextContents:(NSString *)stringToFormat
{
// THIS WORKS (NO MORE ROTATION CRASH)
NSMutableAttributedString *richTxtContent = [[NSMutableAttributedString alloc]initWithString:stringToFormat];
NSRange myRange;
myRange.location = 0;
myRange.length = richTxtContent.length;
[richTxtContent addAttributes:[self commonAttributesForFrontEndRichText] range:myRange];
return richTxtContent;
}
1 ответ
У меня похожая ситуация происходит в моем приложении.
[NSMutableAttributedString initWithData:]
возврат может занять очень много времени, особенно для больших входов. Я предполагаю, что во время выполнения этого вызова код обработки ротации UIKit должен быть запущен, но, поскольку ваш основной поток застрял в вызове initWithData:, дела идут не так, как надо.
Попробуйте переместить вызов синтаксического анализа от основного потока, чтобы он не блокировал его:
+(NSAttributedString *)formatRawFacebookContentForFrontEndRichTextContents:(NSString *)stringToFormat completion:(void (^)(NSAttributedString *))completion
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
NSData *dataContent = [stringToFormat dataUsingEncoding:NSUTF8StringEncoding];
NSMutableAttributedString *richTxtContent = [[NSMutableAttributedString alloc] initWithData:dataContent options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,NSCharacterEncodingDocumentAttribute: [NSNumber numberWithInt:NSUTF8StringEncoding]} documentAttributes:nil error:nil];
NSRange myRange;
myRange.location = 0;
myRange.length = richTxtContent.length;
[richTxtContent addAttributes:[self commonAttributesForFrontEndRichText] range:myRange];
dispatch_async(dispatch_get_main_queue(), ^{
if (completion)
completion(richTxtContent);
})
});
}
Также возможно, что во время вашего вращения некоторый объект, связанный с вашим методом, освобождается, вызывая EXC_BAD_ACCESS. Вы должны будете сделать некоторую отладку на - (void)dealloc
и методы вращения, чтобы увидеть, что происходит.
Другая часть соответствующей документации следующая:
Многоядерные соображения: Начиная с OS X v10.4, NSAttributedString использует WebKit для всего импорта (но не для экспорта) документов HTML. Поскольку загрузка документов WebKit не является поточно-ориентированной, ее нельзя использовать в фоновых потоках. Для приложений, связанных в OS X v10.5 и более поздних версиях, если NSAttributedString импортирует документы HTML в любой поток, кроме основного, использование WebKit передается в основной поток через executeSelectorOnMainThread:withObject:waitUntilDone:. Это делает поток операций безопасным, но требует, чтобы основной поток выполнял цикл выполнения в одном из общих режимов. Это поведение можно переопределить, установив значение стандартного пользовательского значения по умолчанию NSRunWebKitOnAppKitThread либо в YES (для получения нового поведения независимо от связи), либо в NO (для получения старого поведения независимо от связи).