2013-12-22 46 views
13

我在tableview中顯示不同類型的內容,並使用不同的自定義方法在heightForRowAtIndexPath中計算每個單元格的高度。NSMutableAttributedString initWithData:導致旋轉的EXC_BAD_ACCESS

其中一個自定義方法意味着將在NSMutableAttributedString一些HTML,然後計算該NSMutableAttributedString的高度。
對於html轉換,我使用新的initWithData:方法。

除了當我旋轉屏幕時,所有的工作都很完美=>我每次都有一個exc_bad_access。

使用儀器/殭屍,我一直能找到錯誤,實際上它是這樣的initWithData:。 (當我刪除此方法並創建一個「簡單」NSMutableAttributedStringinitWithString,我可以更改方向多少時間,我想要的,沒有crash了)。

任何想法爲什麼?

(順便說一句,我的項目中使用ARC)


儀器/殭屍截圖: enter image description here


稱爲heightForRowAtIndexPath定製方法:

< UtilitiesForFrontEndUI heightForFacebookAttributedText:>

+(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轉換定製方法:

< UtilitiesForFrontEndUI formatRawFacebookContentForFrontEndRichTextContents:>

+(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; 
} 

回答

11

我有類似的情況發生在我的應用程序。

[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 10.4,NSAttributedString對所有進口 使用的WebKit(但不包括出口)HTML文檔。 由於WebKit文檔加載不是線程安全的,因此在後臺線程上使用它並不安全。對於在OS X v10.5和更高版本上鍊接的應用程序,如果NSAttributedString導入任何 (但主線程)上的HTML文檔,則通過performSelectorOnMainThread:withObject:waitUntilDone:將WebKit的使用轉移到主線程 。這個 使操作線程安全,但它要求主線程 在一種常用模式下執行運行循環。通過將標準用戶默認值 NSRunWebKitOnAppKitThread的值設置爲YES(以獲取新行爲 而不考慮鏈接)或NO(以獲取舊行爲而不考慮 鏈接),可以覆蓋此行爲 。

Source

+0

謝謝,你可能是正確的(所以我接受的答案)。我使用了TTTAttributedLabel方式,因爲我也希望在這些attributesString中有可點擊的「鏈接」。它的工作完美(在經歷了一段艱難的時期,學習如何正確使用它)=非常快速+靈活且易於集成/管理+委託方法 – macbeb

+2

我想補充一點,蘋果明確表示不要在後臺線程上使用UIKit版本。我通過使用performSelectorOnMainThread解決了這個問題:object:waitUntilDone:它的作用就像一個魅力。 –

+0

@Jesse Naugher我意識到這有點舊,但是你如何結合你所評論的這個答案使用'performSelectorOnMainThread:object:waitUntilDone:'?遇到類似的問題並尋找修復程序。 –