[UILabel drawRect]中的EXC_BAD_ACCESS

时间:2014-04-22 18:48:55

标签: ios objective-c uilabel exc-bad-access

我在EXC_BAD_ACCESS内有[UILabel drawRect],有时在[UILabel setText]内。该问题发生在硬件设备和模拟器中。

我没有覆盖drawRect:方法,也没有对UILabel类做任何其他特殊操作。标签是通过故事板创建的。

我用NSZombiesEnabled检查了这个,然后在调试器暂停执行之前不久收到其中一条消息:

2014-04-22 20:35:42.032 AppName[5621:a0b] *** -[CFString length]: message sent to deallocated instance 0x1191c730

2014-04-22 20:33:43.447 AppName[5607:a0b] *** -[NSConcreteMutableAttributedString length]: message sent to deallocated instance 0x12a58760

UILabel的文字被更改了很多次(可能每秒50次)。

以下是完整的堆栈跟踪,其中调试器在打印上述CFString错误消息后停止:

#0  0x03619811 in ___forwarding___ ()
#1  0x036194ee in _CF_forwarding_prep_0 ()
#2  0x00f38183 in -[NSConcreteMutableAttributedString length] ()
#3  0x00efe25f in -[NSAttributedString enumerateAttributesInRange:options:usingBlock:] ()
#4  0x014c1dea in -[NSAttributedString(UILabelAdditions) _ui_synthesizeAttributedSubstringFromRange:usingDefaultAttributes:] ()
#5  0x014c2d89 in -[UILabel _synthesizedAttributedText] ()
#6  0x014c84da in -[UILabel _drawTextInRect:baselineCalculationOnly:] ()
#7  0x014c7b94 in -[UILabel drawTextInRect:] ()
#8  0x014c9b0e in -[UILabel drawRect:] ()
#9  0x01381d56 in -[UIView(CALayerDelegate) drawLayer:inContext:] ()
#10 0x00c0fdc9 in -[CALayer drawInContext:] ()
#11 0x00c0fcfa in backing_callback(CGContext*, void*) ()
#12 0x00b00cf4 in CABackingStoreUpdate_ ()
#13 0x00c0fc92 in ___ZN2CA5Layer8display_Ev_block_invoke ()
#14 0x00c43b23 in x_blame_allocations ()
#15 0x00c0fafd in CA::Layer::display_() ()
#16 0x00c0fd49 in -[CALayer _display] ()
#17 0x00c0f506 in CA::Layer::display() ()
#18 0x00c0fd23 in -[CALayer display] ()
#19 0x00c03ed3 in CA::Layer::display_if_needed(CA::Transaction*) ()
#20 0x00c03f4c in CA::Layer::layout_and_display_if_needed(CA::Transaction*) ()
#21 0x00b6bae6 in CA::Context::commit_transaction(CA::Transaction*) ()
#22 0x00b6ce71 in CA::Transaction::commit() ()
#23 0x00c38aea in CA::Display::DisplayLink::dispatch_items(unsigned long long, unsigned long long, unsigned long long) ()
#24 0x00c38f6b in CA::Display::TimerDisplayLink::callback(__CFRunLoopTimer*, void*) ()
#25 0x035e7bd6 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ ()
#26 0x035e75bd in __CFRunLoopDoTimer ()
#27 0x035cf628 in __CFRunLoopRun ()
#28 0x035ceac3 in CFRunLoopRunSpecific ()
#29 0x035ce8db in CFRunLoopRunInMode ()
#30 0x035549e2 in GSEventRunModal ()
#31 0x03554809 in GSEventRun ()
#32 0x01317d3b in UIApplicationMain ()
#33 0x00002f0d in main at (I've cut the path to the project's home.)/main.m:18
#34 0x02d98725 in start ()

为什么会发生此错误?该怎么办?

狂野猜测:我是否必须以线程安全的方式以某种方式访问​​UILabel

更新

文本更改的代码是:

- (void)updateTimeLabels:(NSTimeInterval)timeInterval {
    NSDate *timeIntervalDate = [NSDate dateWithTimeIntervalSince1970:timeInterval];
    NSString *timeIntervalStr = [_TIME_FORMATTER stringFromDate:timeIntervalDate];
    NSString *timeSecondfractionStr = [_SECONDFRACTION_FORMATTER stringFromDate:timeIntervalDate];

    if (![NSThread isMainThread]) { // i've added these 3 lines for checking
        NSLog(@"%s: not on the main thread", __FUNCTION__); // I have not observed this being printed ever
    }

    self.timeCodeLabel.text = timeIntervalStr; // this is the line where sometimes the error takes place
    self.timeCodeSecondfractionLabel.text = timeSecondfractionStr;
}

1 个答案:

答案 0 :(得分:3)

错误表示您的标签已被解除分配,并且您正在尝试向死对象(僵尸)发送消息。

可能会发生 - 我猜 - 如果您尝试从后台线程设置标签文本,但可能不会。

您更有可能过度释放标签(手动引用计数)或者没有强烈引用它(ARC),因此它正在被释放。请发布有关标签对象生命周期的代码。他们是如何被创造出来的?您是否将标签添加为当前视图控制器内容视图的子视图?你是否对标签保持强烈的引用?

如果您正在使用手动引用计数,那么您如何处理标签的生命周期?