【问题标题】:Why does my app crash when backgrounding when using [NSAttributedString initWithData]为什么我的应用程序在使用 [NSAttributedString initWithData] 时在后台运行时崩溃
【发布时间】:2016-12-08 11:11:16
【问题描述】:

我有一个管理 UICollectionView 的 viewController。我有一个从 cellForItemAtIndexPath 调用的辅助方法,它为单元格中的标签提供 NSAttributedString。辅助方法从 html 字符串格式化 NSAttributedString。应用程序在移动到后台时会崩溃,但前提是 indexPath.item 大于 1。换句话说,我可以退出应用程序而不会从第一个或第二个单元格崩溃,但在第三个或第四个单元格始终崩溃。 .. 细胞。

这是我的辅助方法和堆栈跟踪。知道为什么我在退出应用程序时会崩溃吗?

#pragma mark - === Utility Methods === -

- (NSAttributedString *)stepDescriptionStringForIndexPath:(NSIndexPath *)indexPath {

    NSString *headerString;
    NSString *htmlString;
    NSString *categoryString = [NSString stringWithFormat:@"Category: %@", self.knot.category.categoryName];
    NSString *abokString = [NSString stringWithFormat:@"ABOK #: %@", self.knot.abokNumber];
    NSMutableString *activitiesString = [NSMutableString stringWithCapacity:10];
    [activitiesString appendString:@"Activities: "];

    // build a string of activities to append to the description html
    NSArray *activities = [self.knot.activities allObjects];
    if ([activities count] > 0) {
        int counter = 1;
        for (Activity *activity in activities) {
            [activitiesString appendString:activity.activityName];
            if (counter < [activities count]) {
                [activitiesString appendString:@", "];
            }
            counter ++;
        }
    }

    // build an HTML string by concatinating the activities to the step description
    // and add the header string
    if(indexPath.item > 0){
        Step *step = (Step *)self.steps[indexPath.item - 1];
        headerString = [NSString stringWithFormat:@"Step %ld of %lu", (long)indexPath.item, (unsigned long)[self.steps count]];
        htmlString =[NSString stringWithFormat:@"<p>%@</p>%@", headerString, step.stepDescription];
    } else {
        headerString = @"Overview";
        htmlString = [NSString stringWithFormat:@"<p>%@</p>%@<p>%@</br>%@</br>%@</p>", headerString, self.knot.knotDescription, categoryString, abokString, activitiesString];

    }

    // convert the html string to an attributed string
    NSMutableAttributedString *attrStringFromHTML = [[NSMutableAttributedString alloc] initWithData:[htmlString dataUsingEncoding:NSUTF8StringEncoding]
                                                                                            options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
                                                                                                      NSCharacterEncodingDocumentAttribute: [NSNumber numberWithInt:NSUTF8StringEncoding]}
                                                                                 documentAttributes:nil
                                                                                              error:nil];

    // set the font for the body
    NSRange totalRange;
    totalRange.location = 0;
    totalRange.length = attrStringFromHTML.length;
    [attrStringFromHTML addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:16] range:totalRange];

    // set the font for the header
    NSString *temp = [attrStringFromHTML string];

    NSRange headerRange = [temp rangeOfString:headerString];
    NSRange categoryRange = [temp rangeOfString:categoryString];
    NSRange abokRange = [temp rangeOfString:abokString];
    NSRange activitiesRange = [temp rangeOfString:activitiesString];

    [attrStringFromHTML addAttribute:NSFontAttributeName value:[UIFont boldSystemFontOfSize:18] range:headerRange];
    //set the font for the activities paragraph
    if(indexPath.item == 1){

        [attrStringFromHTML addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:12] range:categoryRange];
        [attrStringFromHTML addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:12] range:abokRange];
        [attrStringFromHTML addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:12] range:activitiesRange];


    }
    return attrStringFromHTML;
}
*** 由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“意外的启动状态” *** 首先抛出调用堆栈: ( 0 核心基础 0x00000001131aad85 __exceptionPreprocess + 165 1 libobjc.A.dylib 0x0000000112c1edeb objc_exception_throw + 48 2 CoreFoundation 0x00000001131aabea +[NSException raise:format:arguments:] + 106 3 基础 0x0000000110b96e1e -[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:] + 169 4 UIKit 0x00000001113a7d4e _prepareForCAFlush + 256 5 UIKit 0x00000001113b40b4 _beforeCACommitHandler + 12 6 核心基础 0x00000001130cfc37 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23 7 核心基础 0x00000001130cfba7 __CFRunLoopDoObservers + 391 8 核心基础 0x00000001130c511c CFRunLoopRunSpecific + 524 9 UIFoundation 0x000000011a697a7a - [NSHTMLReader _loadUsingWebKit] + 2093 10 UIFoundation 0x000000011a698e74 -[NSHTMLReader 属性字符串] + 22 11 UIFoundation 0x000000011a6323c0 _NSReadAttributedStringFromURLOrData + 5623 12 UIFoundation 0x000000011a630d34-[NSAttributedString(NSAttributedStringUIFoundationAdditions) initWithData:options:documentAttributes:error:] + 115 13 WhatKnotToDo 0x000000010e84d3ac-[CSC_iPad_KnotDetailViewController stepDescriptionStringForIndexPath:] + 2476 14 WhatKnotToDo 0x000000010e84c31d -[CSC_iPad_KnotDetailViewController 集合视图:cellForItemAtIndexPath:] + 477 15 UIKit 0x0000000111bff08f-[UICollectionView _createPreparedCellForItemAtIndexPath:withLayoutAttributes:applyAttributes:isFocused:] + 483 16 UIKit 0x0000000111c02d96-[UICollectionView _updateVisibleCellsNow:] + 4988 17 UIKit 0x0000000111c07575-[UICollectionView layoutSubviews] + 258 18 UIKit 0x0000000111442980-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 703 19 QuartzCore 0x0000000112af6c00 -[CALayer layoutSublayers] + 146 20 石英核心 0x0000000112aeb08e _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 366 21 石英核心 0x0000000112aeaf0c _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24 22 石英核心 0x0000000112adf3c9 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 277 23 石英核心 0x0000000112b0d086 _ZN2CA11Transaction6commitEv + 486 24 UIKit 0x0000000111394a0b __65-[UIApplication_beginSnapshotSessionForScene:withSnapshotBlock:]_block_invoke2222 + 601 25 UIKit 0x0000000111395201 __65-[UIApplication_performSnapshotsWithAction:forScene:completion:]_block_invoke2243 + 131 26 前板服务 0x00000001153e3039 -[FBSSceneSnapshotAction _finishAllRequests] + 65 27 FrontBoardServices 0x00000001153e2de3 -[FBSSceneSnapshotAction executeRequestsWithHandler:completionHandler:expirationHandler:] + 218 28 UIKit 0x0000000111395024 __65-[UIApplication_performSnapshotsWithAction:forScene:completion:]_block_invoke + 305 29 UIKit 0x0000000111394592-[UIApplication_beginSnapshotSessionForScene:withSnapshotBlock:] + 1138 30 UIKit 0x0000000111394eb2-[UIApplication_performSnapshotsWithAction:forScene:completion:] + 629 31 UIKit 0x0000000111394bbc-[UIApplication_handleSnapshotAction:forScene:completion:] + 153 32 UIKit 0x0000000111390a8f __102-[UIApplication_handleApplicationDeactivationWithScene:shouldForceExit:transitionContext:completion:]_block_invoke1993 + 290 33 UIKit 0x0000000111390657 __102-[UIApplication_handleApplicationDeactivationWithScene:shouldForceExit:transitionContext:completion:]_block_invoke1979 + 1258 34 UIKit 0x0000000111393f62 _runAfterCACommitDeferredBlocks + 317 35 UIKit 0x00000001113a7e4c _cleanUpAfterCAFlushAndRunDeferredBlocks + 95 36 UIKit 0x00000001113b4147 _afterCACommitHandler + 90 37 核心基础 0x00000001130cfc37 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23 38 核心基础 0x00000001130cfba7 __CFRunLoopDoObservers + 391 39 核心基础 0x00000001130c57fb __CFRunLoopRun + 1147 40 核心基础 0x00000001130c50f8 CFRunLoopRunSpecific + 488 41 图形服务 0x0000000115203ad2 GSEventRunModal + 161 42 UIKit 0x0000000111387f09 UIApplicationMain + 171 43 WhatKnotToDo 0x000000010e820b7f 主要 + 111 44 libdyld.dylib 0x000000011396592d 开始 + 1 45 ??? 0x0000000000000001 0x0 + 1 ) libc++abi.dylib:以 NSException 类型的未捕获异常终止

【问题讨论】:

  • 您是否尝试过设置断点并单步执行函数以确定崩溃的确切位置?
  • 你有没有想过解决这个问题?目前我也遇到了同样的问题。
  • 我也是——有什么更新吗?
  • 有什么新东西吗?我也被这个打击了。
  • 你解决了这个问题吗?发生在我身上同样的事情

标签: ios


【解决方案1】:

我也遇到过这个问题,几个小时后,我找到了解决方案。

您只需要包装将NSAttributedString 转换为dispatch_async 的代码。

例如:

   DispatchQueue.MainQueue.DispatchAsync(() =>
        {
            var encodingData = ((NSString)html).Encode(NSStringEncoding.Unicode, true);
            NSAttributedString data = new NSAttributedString(
            encodingData,
            new NSAttributedStringDocumentAttributes()
            {
                DocumentType = NSDocumentType.HTML,

            }, ref error);
        });

我使用的是 Xamarin,所以这些是 C# 代码,但我相信它们在 Swift 和 Obj C 中是相似的。

看起来当系统在页面(视图控制器)之间进行转换时,它会尝试防止在 UI 线程上运行任何繁重的任务。导致此问题的原因。

【讨论】:

  • 秘密是“async”(远不止“main”)。将 NSAttributedString() 作为“同步”运行会导致 OP 报告崩溃。将调用包装在 DispatchQueue.main.async{}
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-08
  • 1970-01-01
  • 2017-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多