我有一个自定义UITableViewCell
(实际上我已经为不同的表分了几次),偶尔表会开始“降级”并慢慢崩溃。重现崩溃是不可能的,它会在以下调用堆栈中崩溃:
特定应用信息:
订单远程无法及时恢复
经过的总CPU时间(秒):0.240(用户0.040,系统0.200),12%CPU
经过的应用程序CPU时间(秒):0.000,0%CPU
Thread 0:
0 libSystem.B.dylib 0x310932b8 semaphore_wait_trap + 8
1 libSystem.B.dylib 0x310c0b46 semaphore_wait + 2
2 libSystem.B.dylib 0x3116a7c4 _dispatch_semaphore_wait_slow + 296
3 libSystem.B.dylib 0x31169cb4 _dispatch_barrier_sync_f_slow + 128
4 CoreFoundation 0x3042bb70 __CFMachPortPerform + 92
5 CoreFoundation 0x304236f8 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 20
6 CoreFoundation 0x304236bc __CFRunLoopDoSource1 + 160
7 CoreFoundation 0x30415f76 __CFRunLoopRun + 514
8 CoreFoundation 0x30415c80 CFRunLoopRunSpecific + 224
9 CoreFoundation 0x30415b88 CFRunLoopRunInMode + 52
10 GraphicsServices 0x31eec4a4 GSEventRunModal + 108
11 GraphicsServices 0x31eec550 GSEventRun + 56
12 UIKit 0x313cf322 -[UIApplication _run] + 406
13 UIKit 0x313cce8c UIApplicationMain + 664
14 Order Remote 0x00002a02 0x1000 + 6658
15 Order Remote 0x000029cc 0x1000 + 6604
这就是崩溃时的样子......
http://img819.imageshack.us/i/uitableviewmissingdata2.jpg/
http://img220.imageshack.us/i/uitableviewmissingdata1.jpg/
我已经浏览了所有内存管理代码并启用了僵尸,并检查了我如何将单元格子类化,我无法看到我出错的地方。请帮帮我。
...
这是一些代码
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MenuItemCell *cell = (MenuItemCell *)[tableView dequeueReusableCellWithIdentifier:@"MenuItemCell"];
if (cell == nil)
{
cell = [[[MenuItemCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"MenuItemCell"] autorelease];
DLog( @"MenuViewController::cellForRowAtIndexPath: allocating memory for a MenuItemCell" );
}
else
{
DLog( @"MenuViewController::cellForRowAtIndexPath: dequeuing an existing MenuItemCell for reuse" );
}
cell.accessoryType = UITableViewCellAccessoryNone;
// only display the item modifiers view if the item has one or more modifiers
if( [[selectedCategory getModifiers] count] > 0 )
{
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
}
// Configure the cell.
cell.textLabel.text = [[items objectAtIndex:indexPath.row] name];
// build a mutable string from the modifiers and set the text to the result in the detail label
NSMutableString* modifiers = [[NSMutableString alloc] initWithString:@""];
Item* i = [items objectAtIndex:indexPath.row];
for( ItemModifier* modifier_iterator in [i modifiers] )
{
[modifiers appendString: [modifier_iterator name]];
[modifiers appendString: @" "];
}
cell.detailTextLabel.text = modifiers;
[modifiers release];
modifiers = nil;
[cell setItem: i];
return cell;
}
@interface MenuItemCell:UITableViewCell { UILabel * itemCount; }
- (void) setItem: (Item*) item;
- (void) resetItemCount;
@end
@implementation MenuItemCell
- (id) initWithStyle: (UITableViewCellStyle) style reuseIdentifier: (NSString*) reuseIdentifier
{
if( (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) )
{
itemCount = [[UILabel alloc] initWithFrame:CGRectZero];
[[self contentView] addSubview:itemCount];
}
return self;
}
- (void) resetItemCount
{
[itemCount setText: @""];
[self setNeedsDisplay];
}
- (void) layoutSubviews
{
[super layoutSubviews];
float inset = 10.0;
CGRect bounds = [[self contentView] bounds];
float h = bounds.size.height;
float w = bounds.size.width;
CGRect accessoryViewBounds;
if( !self.accessoryView )
{
accessoryViewBounds = CGRectZero;
}
else
{
accessoryViewBounds = self.accessoryView.bounds;
}
CGRect textLabelBounds = self.textLabel.bounds;
CGRect innerFrame = CGRectMake( round( inset + w / 2), textLabelBounds.origin.y, round( w / 2 - accessoryViewBounds.size.width - inset * 3 ), h - 1 );
if( ( innerFrame.size.height >= bounds.size.height ) || ( innerFrame.size.width >= bounds.size.width ) )
{
[NSException raise:@"inner frame for MenuItemCell is larger than the contentView bounds" format:@"MenuItemCell (w: %d h: %d) contentView (w: %d h: %d)", innerFrame.size.width, innerFrame.size.height, bounds.size.width, bounds.size.height];
}
// move the rectange to the right side of the cell
itemCount.textAlignment = UITextAlignmentRight;
itemCount.textColor = [UIColor redColor];
itemCount.highlightedTextColor = [UIColor whiteColor];
itemCount.font = [UIFont boldSystemFontOfSize:[UIFont labelFontSize]];
[itemCount setFrame: innerFrame];
}
- (void) setItem: (Item*) item
{
if( [item count] > 0 )
{
[itemCount setText: [NSString stringWithFormat: @"%d", [item count]]];
}
else
{
[itemCount setText: @""];
}
[self setNeedsDisplay];
DLog( @"MenuItemCell::itemCount %@ %d", [item name], [item count] );
}
- (void) dealloc
{
[itemCount release];
itemCount = nil;
[super dealloc];
}
@end
答案 0 :(得分:0)
问题可能是(我无法确认,因为行为是如此不稳定和不可重现)与未在viewDidUnload中释放IBOutlet定义的指针有关。在重新阅读文档之前,我没有意识到他们被保留了。
我还将所有简单的访问器更改为@properties,而不是定义自己的访问器以降低躲避内存管理技术的风险。
...
@interface MenuViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
{
IBOutlet UITableView* itemsTable;
NSMutableArray* items;
Category* selectedCategory;
Order* editingOrder;
NSIndexPath* selectedRow;
BOOL addItemToExistingOrder;
}
-(id)initWithCategory: (Category*)category;
-(IBAction)addItem: (id)sender;
@property (assign) Category* selectedCategory;
@property (assign) NSMutableArray* items;
@property (assign) Order* editingOrder;
@property (assign) BOOL addItemToExistingOrder;
@implementation
- (void)viewDidUnload
{
[super viewDidUnload];
[selectedRow release];
selectedRow = nil;
[itemsTable release];
itemsTable = nil;
}