UITableView с пользовательским UITableViewCell не отображается должным образом - PullRequest
0 голосов
/ 20 марта 2011

У меня есть пользовательский UITableViewCell (на самом деле я подклассировал его несколько раз для разных таблиц), и иногда таблица начинает «деградировать» и медленно падать. Невозможно воспроизвести сбой, и он падает со следующим стеком вызовов:

Информация о приложении:
Не удалось возобновить заказ пульта в срок

Истекшее общее время ЦП (в секундах): 0,240 (пользователь 0,040, система 0,200), 12% ЦП
Истекшее время ЦП приложения (в секундах): 0,000, 0% ЦП

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

1 Ответ

0 голосов
/ 07 апреля 2011

Вероятно, проблема была (я не могу подтвердить, потому что поведение было настолько непредсказуемым и невоспроизводимым), связанная с не выпуском определенных в IBDutlet указателей в viewDidUnload.Я не понимал, что они были сохранены до перечитывания документов.

Я также изменил все свои простые средства доступа на @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;
}
...