如何调试 iPhone 应用程序崩溃日志。仅在 App Store 购买的版本中崩溃,而不是在开发中

Posted

技术标签:

【中文标题】如何调试 iPhone 应用程序崩溃日志。仅在 App Store 购买的版本中崩溃,而不是在开发中【英文标题】:How to debug iPhone app crash log. Crash only in App Store purchased version, not in development 【发布时间】:2011-05-01 09:59:04 【问题描述】:

我收到了第一份崩溃报告,但我无法了解问题所在。 幸运的是,由于这个崩溃来自我的一个同事,我可以直接在他的 iPhone 上测试错误并在他的手机上安装开发版本。

但是,奇怪的是,当我从我的计算机上在他的设备上安装并运行开发版本时,并没有崩溃; 只有从 App Store 下载并安装应用程序时才会出现崩溃。 到目前为止,我无法在任何其他设备上重现该错误(受影响的设备是 iPhone 3G 固件 4.2.1,所有操作系统运行速度都很慢)。

崩溃发生在从 UITableViewController (ItemsListTableViewController) 中选择一行之后,此时应该会出现一个详细视图,但是在构建详细视图 (ItemDetailViewController) 期间应用程序崩溃viewDidLoad

特别是问题似乎在类 LocationPathView(ItemDetailViewController 的视图的子视图)中本地化。 ItemDetailViewController 是 UITableViewController 的子类,并从 viewDidLoad 中的 nib 加载其 tableHeaderView: [[NSBundle mainBundle] loadNibNamed:@"ItemDetailHeaderView" owner:self options:nil]; (LocationPathView 是 tableHeaderView 的一部分

加载nib文件时,会调用LocationPathView::awakeFromNib,然后调用LocationPathView::layoutSubviews。崩溃似乎源于 layoutSubviews。 在 layoutSubviews 我执行动画: [UIView beginAnimations:nil context:nil]; [UIView setAnimationDuration:0.2]; 由于某些原因,这个动画会在慢速设备上造成崩溃吗?在 layoutSubviews 中设置动画是否正确?

如果有任何帮助,我将不胜感激, 马可

Date/Time:       2011-04-30 12:50:36.972 +0200
OS Version:      iPhone OS 4.2.1 (8C148)
Report Version:  104

Exception Type:  EXC_CRASH (SIGABRT)
Exception Codes: 0x00000000, 0x00000000
Crashed Thread:  0

Thread 0 Crashed:
0   libSystem.B.dylib               0x35de3ad0 __kill + 8
1   libSystem.B.dylib               0x35de3abe kill + 4
2   libSystem.B.dylib               0x35de3ab2 raise + 10
3   libSystem.B.dylib               0x35dfad5e abort + 54
4   libstdc++.6.dylib               0x374f2a00 __gnu_cxx::__verbose_terminate_handler() +    588
5   libobjc.A.dylib                 0x32d9d8d8 _objc_terminate + 160
6   libstdc++.6.dylib               0x374f0100 __cxxabiv1::__terminate(void (*)()) + 76
7   libstdc++.6.dylib               0x374f0178 std::terminate() + 16
8   libstdc++.6.dylib               0x374f02a0 __cxa_throw + 100
9   libobjc.A.dylib                 0x32d9bf28 objc_exception_throw + 104
10  CoreFoundation                  0x3759dabc +[NSException raise:format:arguments:] + 64
11  CoreFoundation                  0x3759daf0 +[NSException raise:format:] + 24
12  QuartzCore                      0x33d9409c CALayerSetPosition(CALayer*, CA::Vec2<double> const&, bool) + 180
13  QuartzCore                      0x33d93fd8 -[CALayer setPosition:] + 40
14  QuartzCore                      0x33d93efc -[CALayer setFrame:] + 444
15  UIKit                           0x358d92c8 -[UIView(Geometry) setFrame:] + 248
16  UIKit                           0x3592dde0 -[UIButton setFrame:] + 120
17  MyApp                       0x0003432a -[LocationPathView layoutSubviews] (LocationPathView.m:101)    <<<<<<<<<<<<<<<<<<<<<<<<<<<
18  UIKit                           0x358ec704 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 32
19  CoreFoundation                  0x37538f72 -[NSObject(NSObject) performSelector:withObject:] + 18
20  QuartzCore                      0x33d9a128 -[CALayer layoutSublayers] + 176
21  QuartzCore                      0x33d99db0 CALayerLayoutIfNeeded + 192
22  QuartzCore                      0x33d99cd8 -[CALayer layoutIfNeeded] + 108
23  UIKit                           0x3598ee38 -[UIView(Hierarchy) layoutIfNeeded] + 24
24  UIKit                           0x359fbabc -[UIButton titleLabel] + 76
25  MyApp                       0x0001fee8 -[ItemDetailViewController viewDidLoad] (ItemDetailViewController.m:148)     <<<<<<<<<<<<<<<<<<<<<<<<<<<
26  UIKit                           0x35926e58 -[UIViewController view] + 152
27  UIKit                           0x35937f2c -[UIViewController contentScrollView] + 24
28  UIKit                           0x35937d4c -[UINavigationController _computeAndApplyScrollContentInsetDeltaForViewController:] + 36
29  UIKit                           0x35937bf8 -[UINavigationController _layoutViewController:] + 28
30  UIKit                           0x35937474 -[UINavigationController _startTransition:fromViewController:toViewController:] + 336
31  UIKit                           0x35937288 -[UINavigationController _startDeferredTransitionIfNeeded] + 256
32  UIKit                           0x35926c44 -[UINavigationController pushViewController:transition:forceImmediate:] + 904
33  UIKit                           0x359268a8 -[UINavigationController pushViewController:animated:] + 36
34  MyApp                       0x00020a9a -[ItemsListTableViewController viewItemDetail:startEditable:] (ItemsListTableViewController.m:717)
35  MyApp                       0x00022110 -[ItemsListTableViewController tableView:didSelectRowAtIndexPath:] (ItemsListTableViewController.m:241)  <<<<<<<<<<<<<<<<<<<<<<<<<<<
36  UIKit                           0x3595bf4c -[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:] + 884
37  UIKit                           0x35a5da9c -[UITableView _userSelectRowAtPendingSelectionIndexPath:] + 196
38  Foundation                      0x351724d4 __NSFireDelayedPerform + 360
39  CoreFoundation                  0x375522fe __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 10
40  CoreFoundation                  0x37551cd2 __CFRunLoopDoTimer + 982
41  CoreFoundation                  0x37521a8a __CFRunLoopRun + 1178
42  CoreFoundation                  0x37521504 CFRunLoopRunSpecific + 220
43  CoreFoundation                  0x37521412 CFRunLoopRunInMode + 54
44  GraphicsServices                0x33e76d1c GSEventRunModal + 188
45  UIKit                           0x3591d574 -[UIApplication _run] + 580
46  UIKit                           0x3591a550 UIApplicationMain + 964
47  MyApp                       0x00002fce main (main.m:14)
48  MyApp                       0x00002f98 0x1000 + 8088

ItemsListTableViewController.m:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
    Item *item = [self.fetchedResultsController objectAtIndexPath:indexPath];
    [self viewItemDetail:item startEditable:NO];    <<<<<<<<<<<<<<<<<<<



- (void)viewItemDetail:(Item *)item  startEditable:(BOOL)editable 
    ItemDetailViewController *controller = [[ItemDetailViewController alloc] initWithStyle:UITableViewStyleGrouped showItem:item inItemsList:[self.fetchedResultsController fetchedObjects]];   

    if (editable)
        controller.editing = YES;

    [self.navigationController pushViewController:controller animated:YES];    <<<<<<<<<<<<<<<<<<<
    [controller release];

ItemDetailViewController.m:

- (void)viewDidLoad 
    [super viewDidLoad];

    self.navigationItem.title = NSLocalizedString(@"Item details", @"Item details");
    self.navigationItem.rightBarButtonItem = self.editButtonItem;

    self.view.backgroundColor = [UIColor groupTableViewBackgroundColor];

    // Configure the tableview
    self.tableView.sectionFooterHeight = 5.0f;
    self.tableView.allowsSelectionDuringEditing = YES;

    // Create and set the tableview header
    if (headerView == nil) 
        [[NSBundle mainBundle] loadNibNamed:@"ItemDetailHeaderView" owner:self options:nil];    <<<<<<<<<<<<<<<<<<<<<<<<<<<

        // Item title button
        itemTitleButton.titleLabel.adjustsFontSizeToFitWidth = YES;
        itemTitleButton.titleLabel.minimumFontSize = 11.0f;
        [itemTitleButton setImageEdgeInsets:UIEdgeInsetsMake(0.0f, itemTitleButton.bounds.size.width-29.0f, 0.0f, 0.0f)];
        [itemTitleButton setTitleEdgeInsets:UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 24.0f)];
        UIImage *normalImage = [[UIImage imageNamed:@"objectNameHighlighedButton.png"] stretchableImageWithLeftCapWidth:11 topCapHeight:0];
        [self.itemTitleButton setBackgroundImage:normalImage forState:UIControlStateHighlighted];

        [pathView addTarget:self action:@selector(moveButtonTouchUp:) forControlEvents:UILocationPathViewMoveControlEvent];

        // Check if the item's path should be recalculated
        if (pathView.pathList == nil) 
            pathView.pathList = pathNames;
        

        self.tableView.tableHeaderView = headerView;

        // Save initial header height so that it can be restore navigating between items with different flags count
        tableHeaderFrameHeight = headerView.frame.size.height;
    


    // Enable the UIToolbar at the bottom of the view controller and create its buttons
    [self.navigationController setToolbarHidden:NO animated:YES];
    self.navigationController.toolbar.barStyle = UIBarStyleBlack;
    self.navigationController.toolbar.translucent = YES;

    // [omitted part]: create toolbar items …

    // Restore editing status if the view was unloaded
    if (viewUnloaded && self.editing) 
        viewUnloaded = NO;
        // this will force setEditing:YES to be called on all tableView's subviews! (categorySectionHeaderView...)
        [self.tableView setEditing:YES];
        // ...not for tableheader!
        editableImageView.editing = YES;
        pathView.editing = YES;
    

    // Recreate item flags
    CGRect headerFrame = headerView.frame;
    for (FlaggedItem *flagObject in self.itemBookmarkRibbons) 
        headerFrame.size.height += ITEM_SHEET_FLAG_BUTTON_HEIGHT + 8.0f;
        headerView.frame = headerFrame;

        UIButton *bookmarkRibbon = [self createBookmarkRibbon:flagObject];
        bookmarkRibbon.frame = CGRectMake(0.0f, headerFrame.size.height-ITEM_SHEET_FLAG_BUTTON_HEIGHT-8.0f, 
                                      headerFrame.size.width, ITEM_SHEET_FLAG_BUTTON_HEIGHT);

        [headerView addSubview:bookmarkRibbon];
        [headerView sendSubviewToBack:bookmarkRibbon];
    

    // Update the table header view height
    self.tableView.tableHeaderView = headerView;

LocationPathView.m:

- (void)awakeFromNib 
    [super awakeFromNib];

    UIColor *color = [[UIColor alloc] initWithWhite:0.0f alpha:0.0f];
    self.backgroundColor = color;
    [color release];

    [self sendSubviewToBack:backgroundView];
    // create imageview rounded rect
    CALayer *l = [backgroundView layer];
    [l setMasksToBounds:YES];
    [l setCornerRadius:10.0];
    [l setBorderWidth:2.0];
    UIColor *borderColor = [[UIColor alloc] initWithWhite:0.65 alpha:1.0];
    [l setBorderColor:[borderColor CGColor]];
    [borderColor release];

    expanded = NO;
    buttons = [[NSMutableArray alloc] initWithCapacity:2];
    [buttons addObject:[self createButtonOfType:PVButtonTypeStart]];
    [buttons addObject:[self createButtonOfType:PVButtonTypeEnd]];



- (void)layoutSubviews 
#define MOVE_BUTTON_WIDTH       90.0f
#define STANDARD_BUTTON_HEIGHT  22.0f

    [super layoutSubviews];

    CGRect contentRect = self.frame;
    if (CGRectIsEmpty(contentRect))
        return;

    if ([buttons count] != [pathList count] && [pathList count] > 0) 
        [self prepareButtons];
    


    [UIView beginAnimations:nil context:nil];  <<<<<<<<<<<<<<<<<<<
    [UIView setAnimationDuration:0.2];

    CGFloat x = 0.0f, y = 0.0f;
    CGFloat availableHSpace = 0.0f;
    UIButton *button;

    for (NSUInteger i=0; i<[self.buttons count]; i++) 
        button = [buttons objectAtIndex:i];

        if (self.isExpanded == NO && i > 0 && i <= [self.buttons count]-2)
            // hide all middle buttons
            button.alpha = 0.0f;
        else 
            button.alpha = 1.0f;
            NSString *title = [pathList objectAtIndex:i];
            CGSize size = [title sizeWithFont:button.titleLabel.font];

            CGFloat buttonWidth = size.width + 36.0f;
            // check if the button width is greater than available space, if yes set the button width equal to the available space.
            // The available space is reduced in editing move to make room for the move button.
            if (self.editing && moveButton)
                availableHSpace = contentRect.size.width - MOVE_BUTTON_WIDTH - 3.0f - 10.0f; // 10.0=space from move button
            else
                availableHSpace = contentRect.size.width;

            if (x + buttonWidth > availableHSpace)
                buttonWidth = availableHSpace - x;

            button.frame = CGRectMake(x, y, buttonWidth, STANDARD_BUTTON_HEIGHT);
            [button setTitle:title forState:UIControlStateNormal];
            y += STANDARD_BUTTON_HEIGHT + 3.0f; // vertical distance between buttons
        

        if (self.isExpanded)
            x += 14.0f; // indentation
    

    // setup cyan background
    backgroundView.alpha = (self.isExpanded ? 0.80f : 0.0f);
    CGRect backgroundViewFrame = backgroundView.frame;
    if (self.isExpanded) 
        // 10.0 =  5.0=y gap between backgroundView and self  +  5.0=distance between edge
        backgroundViewFrame.size.height = button.frame.origin.y + button.frame.size.height + 12.0f;
    
    else
        backgroundViewFrame.size.height = self.frame.size.height;

    backgroundView.frame = backgroundViewFrame;

    [UIView commitAnimations];

    // set moveButton position and make it visible (put it out of animation block to avoid frame changing animation,
    // fade animation already set from caller)
    if (self.editing && moveButton) 
        moveButton.frame = CGRectMake(0.0f, 0.0f, MOVE_BUTTON_WIDTH, STANDARD_BUTTON_HEIGHT*2 + 3.0f); // 3.0=vertical space between buttons
        moveButton.center = CGPointMake(contentRect.size.width - MOVE_BUTTON_WIDTH/2 - 3.0f, contentRect.size.height/2);
        moveButton.hidden = NO;
    

【问题讨论】:

【参考方案1】:

只有应用商店版本出错让我怀疑用于构建提交二进制文件的项目或目标设置。

您是否使用项目配置来构建提交二进制文件?如果是这样,我要寻找的第一件事是为发布版本错误地定义了 C 宏。或者它在项目级别是正确的,但在目标级别是不正确的。也许您的动画块的结尾没有正确发出信号?

使用与您的应用商店版本完全相同的设置构建应用的临时版本将是一个很好的测试。 (代码签名将是唯一的区别。)从设备中删除旧应用程序并通过 iTunes 进行部署以确保。

【讨论】:

我正在以标准方式构建我的发布版本:我在 Build Settings -> Code Signing Identity 中选择了我的分发配置文件进行调试和发布行,然后是 Product -> Archive。尚未使用 ad-hoc 版本进行测试,我会尽快发布结果 类似的事情发生在我身上。特别是为 UITableView 中的节标题创建 UIView。如果我存档并“共享”我的应用程序,然后将其安装在 iPhone 4 上,一切都会很好。如果我“提交”相同的构建,我会得到这个:CALayerInvalidGeometry',原因:'CALayer bounds contains NaN:【参考方案2】:

可能是您的动画块阻止了后面运行的主要过渡。尽量避免这种情况。例如 popAviewController 并且在 push 另一种情况之后会导致崩溃,因为您在前一个完成之前正在执行另一个转换。希望你能理解。

【讨论】:

“主过渡”是指由 pushViewController:animated: 启动的动画吗?您应该建议将我的动画放在哪里而不是放在 layoutSubviews 中? 过渡完成后

以上是关于如何调试 iPhone 应用程序崩溃日志。仅在 App Store 购买的版本中崩溃,而不是在开发中的主要内容,如果未能解决你的问题,请参考以下文章

iPhone 应用程序仅在 3G 上的发布模式下崩溃

从Xcode 10部署到运行iOS 12的iPhone时,应用程序立即崩溃

iPhone模拟器生成的崩溃日志?

如何调试仅在发布版本中发生的崩溃[关闭]

如何调试仅在应用程序关闭时发生的崩溃? (德尔福)

iOS崩溃日志 如何看