iPhone:SIGSEGV在设备上看似随机(ViewDidLoad,setFont等),从不在模拟器中

时间:2011-11-01 12:26:05

标签: iphone objective-c ios uiviewcontroller exc-bad-access

首先,提前感谢您花时间阅读此内容。我几天来一直在寻找这个问题的答案,但我似乎无法找到我想要的东西。我知道SIGSEGV错误(或EXEC_BAD_ACCESS错误)通常是由内存管理问题引起的,但是经过几个小时的查看代码后,我似乎无法找到错误。静态分析仪也找不到任何东西。

正如标题所说,此错误仅发生在设备上(从不在模拟器中),并且每次给定视图加载时都不会发生。显然这意味着我无法使用NSZombie来调试出错的地方。

让我们从崩溃转储日志开始:

0 myApp 0x00036659 +[TFCrashHandler backtrace] + 428
1 myApp 0x00036a6f TFSignalHandler + 54
2 libsystem_c.dylib 0x32f48539 _sigtramp + 48
3 UIKit 0x365701df -[UIView(Rendering) setNeedsDisplay] + 86
4 UIKit 0x36598269 -[UILabel setFont:] + 232
5 myApp 0x000190eb +[BruUISettings applyLabelDetailStyle:] (BruUISettings.m:130)
6 myApp 0x0001aa57 -[ActiveChallengeViewController viewDidLoad] (ActiveChallengeViewController.m:115)
7 UIKit 0x365a57ff -[UIViewController view] + 166
8 UIKit 0x365b1c39 -[UIViewController contentScrollView] + 24
9 UIKit 0x365b1aa9 -[UINavigationController _computeAndApplyScrollContentInsetDeltaForViewController:] + 36
10 UIKit 0x365b198f -[UINavigationController _layoutViewController:] + 34
11 UIKit 0x365b115b -[UINavigationController _startTransition:fromViewController:toViewController:] + 318
12 UIKit 0x365b0f53 -[UINavigationController _startDeferredTransitionIfNeeded] + 250
13 UIKit 0x365a5673 -[UINavigationController pushViewController:transition:forceImmediate:] + 806
14 UIKit 0x365a5349 -[UINavigationController pushViewController:animated:] + 36
15 myApp 0x00015dc7 -[ChallengesHomeViewController tableView:didSelectRowAtIndexPath:] (ChallengesHomeViewController.m:325)
16 UIKit 0x3661f565 -[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:] + 944
17 UIKit 0x36697ce7 -[UITableView _userSelectRowAtPendingSelectionIndexPath:] + 158
18 Foundation 0x31f7a943 __NSFireDelayedPerform + 414
19 CoreFoundation 0x34ab1a63 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 14
20 CoreFoundation 0x34ab16c9 __CFRunLoopDoTimer + 364
21 CoreFoundation 0x34ab029f __CFRunLoopRun + 1206
22 CoreFoundation 0x34a334dd CFRunLoopRunSpecific + 300
23 CoreFoundation 0x34a333a5 CFRunLoopRunInMode + 104
24 GraphicsServices 0x351a7fed GSEventRunModal + 156
25 UIKit 0x3659a743 UIApplicationMain + 1090
26 myApp 0x000026c5 main (main.m:13)
27 myApp 0x0000265c start + 52

注意,我正在使用来自testflightapp.com的TestFlight,它位于堆栈顶部的异常处理程序。

以下是创建和推送有问题的视图控制器的代码:

CDAcceptedChallenge *challengeAtIndex = [self.activeChallenges objectAtIndex:[indexPath row]];
ActiveChallengeViewController *view = [[ActiveChallengeViewController alloc] initWithNibName:@"ActiveChallengeViewController" 
                                                                                      bundle:nil 
                                                                             activeChallenge:challengeAtIndex];
view.leaveChallengeTarget = self;

[self.navigationController pushViewController:view animated:YES];
[view release];

这个代码在didSelectRowAtIndex方法中运行,如果这很重要的话。这个视图控制器有一堆成员变量和IBOutlets,它们引用了nib中的对象,但这里是与此错误中提到的对象相关的那些:

在.h:

UILabel *helpLabel;
...
@property (nonatomic, retain) IBOutlet UILabel *helpLabel;

in .m:

@synthesize helpLabel;

我很肯定helpLabel绑定到nib中的正确对象,因为它确实在没有爆炸时获得了正确的样式。接下来,这是该视图控制器的init方法:

self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];

if (self) 
{
    self.activeChallenge = inActiveChallenge;
}
return self;

这是viewDidLoad方法,我们有时会看到崩溃(粗体)。请注意,这里有很多内容,但没有触及self.helpLabel,这最终会导致崩溃。

[super viewDidLoad];
[self.navigationController setNavigationBarHidden:FALSE];
self.navigationItem.title = @"Details";

// overlay disclosure creation
self.overlayDisclosure = [CustomColoredDisclosureIndicator accessoryWithColor:self.challengeNameLabel.textColor];
self.overlayDisclosure.highlightedColor = [UIColor whiteColor];
[self.overlayDisclosure addTarget:self action:@selector(overlayViewButtonClick:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.overlayDisclosure];

[[BruNotificationManager instance] registerForTabUpdated:[[[BruCallback alloc] initWithTarget:self 
                                                                                 andCallback:@selector(tabUpdated:)] autorelease]];
[[BruNotificationManager instance] registerForActiveChallengesUpdated:[BruCallback buildFromObject:self 
                                                                                       andCallback:@selector(challengesUpdatedLocally)]];
[[BruNotificationManager instance] registerForEarnedRewardsUpdated:[BruCallback buildFromObject:self 
                                                                                    andCallback:@selector(rewardsUpdatedLocally:)]];

[super refreshEarnedRewardsForChallenge:self.activeChallenge.challenge.identifier];
[super refreshTabForChallenge:self.activeChallenge.challenge.identifier];

UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd 
                                                                           target:self 
                                                                           action:@selector(addBeer)];
self.navigationItem.rightBarButtonItem = addButton;
[addButton release];

// Request that the object download its image
BruCallback *imageCallback = [BruCallback buildFromObject:self andCallback:@selector(imageRequestCompleted:withData:)];
self.challengeImageView.image = [self.activeChallenge.challenge retrieveImage:self.bruConnection withCallback:imageCallback];

// Create our help label
**[BruUISettings applyLabelDetailStyle:self.helpLabel];**
self.helpLabel.textColor = AccentSecondaryColor;

self.overlayView.alpha = [BruUISettings standardOverlayViewAlpha];

[BruUISettings applyTableStyle:self.rewardsTable];
[BruUISettings applyScrollViewStyle:self.scrollView];

self.needToUpdateTab = YES;
self.needToUpdateRewards = YES;
self.needToUpdateChallenge = NO;

这是viewDidUnload方法的精简版本,虽然我不明白为什么在这种情况下它会很重要:

...
self.helpLabel = nil;
...

[super viewDidUnload];

最后,我的[BruUISettings applyLabelDetailStyle]是一种将集中式样式应用于我的标签的方法。我的代码中有很多地方使用这个函数,这样我只需更改一个函数就可以更改这些标签的所有样式。

+ (void) applyLabelDetailStyle:(UILabel *)inLabel
{
    inLabel.font = [UIFont fontWithName:@"Helvetica Neue" size:12.0];
    inLabel.textColor = [UIColor darkGrayColor];
    inLabel.backgroundColor = [UIColor clearColor];
}

对于这里可能发生的事情的任何想法将不胜感激。再次感谢。

2 个答案:

答案 0 :(得分:2)

经过大量调试后,我发现这实际上是由于QSStrings库引起的内存损坏,我用它来生成base64编码的字符串。崩溃似乎是随机发生的,但只有在调用此库之后才会发生。当我切换到另一个MD5库时,问题就消失了。如果您正在使用此库,我建议您找一个新的进行base64编码。我转到了这里找到的那​​个:http://www.cocoadev.com/index.pl?BaseSixtyFour

答案 1 :(得分:0)

我认为问题的发生是因为您的视图中有一些错误,它拥有您的标签(ActiveChallengeViewController的视图)。

当您设置标签的字体时,会调用父视图的setNeedsDisplay,并且因为出现问题,setNeedsDisplay会崩溃。

你的专栏:

self.challengeImageView.image = [self.activeChallenge.challenge retrieveImage:self.bruConnection withCallback:imageCallback];

检索图像是同步连接吗?

如果有时未从您的连接中检索图像,可能会出现此问题,因此图片视图的图片属性不佳。

但我不确定因为setNeedsDisplay没有直接调用视图的重绘,所以我不知道调试器是否只是在setNeedsDisplay之后调用错误。

编辑:

我认为这个答案很糟糕,如果图像不正常,当imageView图像属性保留图像时必须发生崩溃但我在这种情况下让答案可以帮助你指出真正的问题。