сообщение отправлено на освобожденный экземпляр (возможно, UITableViewCell) - PullRequest
0 голосов
/ 31 августа 2011

Я знаю, что многие люди уже сталкивались с этой проблемой, и я прочитал много предложенных решений, ни одно из которых не помогло мне.Я работаю над частью более крупного проекта, включающего три разных представления: первое представление содержит UITableView с пользовательскими ячейками под названием WeekdaySelectionWithPopoverCellController.Эта ячейка содержит метку, обозначающую день недели (с понедельника по пятницу), UISwitch и следующие элементы, которые отображаются или скрываются соответственно в зависимости от состояния переключателя.Если переключатель включен, ячейка выглядит следующим образом:

 ----------------------------------------------------------------------
|  Monday    [ON/off]    between        ( N/A )     and       ( N/A )  |
 ----------------------------------------------------------------------

Если она выключена, она выглядит следующим образом:

 ----------------------------------------------------------------------
|  Monday    [on/OFF]                                                  |
 ----------------------------------------------------------------------

Элементы (N / A) - это кнопки UIB.Если пользователь нажмет одну из этих кнопок, откроется UIPopover с указателем даты.Идея состоит в том, что пользователь выбирает время из средства выбора, которое должно отображаться на кнопках UIB вместо (N / A):

 ----------------------------------------------------------------------
|  Monday    [ON/off]    between      ( 12:30 )     and     ( 16:00 )  |
 ----------------------------------------------------------------------

Скрытие элементов при нажатии на UISwitch работает так же, как иотображение поповера.Однако, если пользователь нажимает кнопку «Готово» во всплывающем окне и всплывающее окно отклоняется, приложение вылетает со следующей ошибкой:

-[UITableViewCell isKindOfClass:]: message sent to deallocated instance 0xf42a100

Как ни странно, единственное место, содержащее код, вызывающий isKindOfClass, - это ModalTableViewController(родительский вид всплывающего окна и пользовательских ячеек) и адрес отображаемого экземпляра не принадлежат ему.Также это не адрес всплывающего окна, который только покидает класс пользовательских ячеек (WeekdaySelectionWithPopoverCellController).

Позвольте мне дать вам соответствующие части ModalTableViewController.m:

@implementation ModalTableViewController

@synthesize mtvcNavigationBar;
@synthesize mtvcTableView;

@synthesize cell;
@synthesize lable;

@synthesize button;

// WeekdaySelectionWithPopoverCell
@synthesize wswpMainLabel;
@synthesize wswpFromLabel;
@synthesize wswpToLabel;
@synthesize wswpOClockFromLabel;
@synthesize wswpOClockToLabel;
@synthesize wswpSwitch;
@synthesize wswpFromValueButton;
@synthesize wswpToValueButton;

@synthesize popoverController;

// more code...

- (ModalTableViewController *)initWithParam:(NSString *)title andData:(NSArray *)myData andSelection:(NSArray *)selection  {

    [self initSwipeLeftNavigation];

    mtvcNavigationBar.topItem.title = title;

    mtvcSectionSize = [myData count];
    mtvcSectionname = @"";

    mtvcLabels = myData;
    mtvcData   = selection;

    [mtvcLabels retain];
    [mtvcData retain];
    [otherValues retain];

    mtvSingleton = [ModalTableViewSingleton sharedInstance];

    return self;
}

// more code...



- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *cellRet;

    NSString *MyIdentifier = @"WeekdaySelectionWithPopoverCellController";

    cellRet = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];

    if (cellRet == nil) {
        [[NSBundle mainBundle] loadNibNamed:MyIdentifier owner:self options:nil];
        cellRet = self.cell;
    }

    NSDictionary *tempValues;
    tempValues = [mtvcData objectAtIndex:indexPath.row];

    wswpSwitch = (UISwitch *)[cellRet viewWithTag:2];
    wswpSwitch.on = [[tempValues valueForKey:@"company_id"] isKindOfClass:[NSNull class]] ? false: true;

    BOOL negatedState = !wswpSwitch.on;

    NSLog(@"tempValues: %@", tempValues);

    lable      = (UILabel *)[cellRet viewWithTag:1];
    lable.text = [NSString stringWithFormat:@"%@", [tempValues valueForKey:@"short"]];
    lable.font = [UIFont boldSystemFontOfSize:16];

    lable        = (UILabel *)[cellRet viewWithTag:3];
    lable.font   = [UIFont boldSystemFontOfSize:16];
    lable.text   = [NSString stringWithFormat:@"%@", @"von"];
    lable.hidden = negatedState;

    lable        = (UILabel *)[cellRet viewWithTag:5];
    lable.text   = [NSString stringWithFormat:@"%@", @"bis"];
    lable.font   = [UIFont boldSystemFontOfSize:16];
    lable.hidden = negatedState;

    lable        = (UILabel *)[cellRet viewWithTag:7];
    lable.text   = @"Uhr";
    lable.font   = [UIFont boldSystemFontOfSize:16];
    lable.hidden = negatedState;

    lable        = (UILabel *)[cellRet viewWithTag:8];
    lable.text   = @"Uhr";
    lable.font   = [UIFont boldSystemFontOfSize:16];
    lable.hidden = negatedState;

    button = (UIButton *)[cellRet viewWithTag:4];
    [self setButtonLabel:button forKey:@"beginning" fromDict:tempValues];
    button.hidden = negatedState;
    /*
    if (![[tempValues valueForKey:@"beginning"] isKindOfClass:[NSNull class]]) {

        button.titleLabel.text = [NSString stringWithFormat:@"%@", [tempValues valueForKey:@"beginning"]];
    } else {
        button.titleLabel.text = @"k.A.";
    }
     */

    button = (UIButton *)[cellRet viewWithTag:6];
    [self setButtonLabel:button forKey:@"until" fromDict:tempValues];
    button.hidden = negatedState;
    /*
    if (![[tempValues valueForKey:@"until"] isKindOfClass:[NSNull class]]) {

        button.titleLabel.text = [NSString stringWithFormat:@"%@", [tempValues valueForKey:@"until"]];
    } else {
        button.titleLabel.text = @"k.A.";
    }
     */

    self.cell = nil;

    return cellRet;
}

- (void)setButtonLabel:(UIButton *)btn forKey:(NSString *)key fromDict:(NSDictionary *)dict {
    [btn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];

    NSString *text = [dict objectForKey:key];
    if ([mtvSingleton.sharedData objectForKey:key]) {
        [btn setTitle:[mtvSingleton.sharedData objectForKey:key] forState:UIControlStateNormal];
    } else {
        if ([text isKindOfClass:[NSNull class]] ||
            [text isEqualToString:@""])
        {
            [btn setTitle:@"k.A." forState:UIControlStateNormal];
        } else {
            [btn setTitle:text forState:UIControlStateNormal];
        }
    }
}

// more code...

- (IBAction)switchButtonValueChanged:(id)sender
{
    //[self changeDisplayState:wsdSwitch.on forObj:sender];
    // UISwitch *tmp = (UISwitch *)sender;
    UIView *v = (UIView *)sender;
    do {
        v = v.superview;
    } while (![v isKindOfClass:[UITableViewCell class]]);
    // WeekdaySelectionWithPopoverCellController *cell1 = (WeekdaySelectionWithPopoverCellController *)v;
    cell = (UITableViewCell *)v;

    wswpSwitch = (UISwitch *)[cell viewWithTag:2];
    BOOL negatedState = !wswpSwitch.on;

    lable = (UILabel *)[cell viewWithTag:3];
    lable.hidden = negatedState;

    lable = (UILabel *)[cell viewWithTag:5];
    lable.hidden = negatedState;

    lable = (UILabel *)[cell viewWithTag:7];
    lable.hidden = negatedState;

    lable = (UILabel *)[cell viewWithTag:8];
    lable.hidden = negatedState;

    button = (UIButton *)[cell viewWithTag:4];
    button.hidden = negatedState;

    button = (UIButton *)[cell viewWithTag:6];
    button.hidden = negatedState;

    /*
    wswpSwitch = (UISwitch *)[cell1 viewWithTag:2];
    BOOL negatedState = !wswpSwitch.on;

    lable = (UILabel *)[cell1 viewWithTag:3];
    lable.hidden = negatedState;

    lable = (UILabel *)[cell1 viewWithTag:5];
    lable.hidden = negatedState;

    lable = (UILabel *)[cell1 viewWithTag:7];
    lable.hidden = negatedState;

    lable = (UILabel *)[cell1 viewWithTag:8];
    lable.hidden = negatedState;

    button = (UIButton *)[cell1 viewWithTag:4];
    button.hidden = negatedState;

    button = (UIButton *)[cell1 viewWithTag:6];
    button.hidden = negatedState;
     */

}

#pragma mark - handlers

- (IBAction)toButtonHandler:(id)sender {
    dppvc = [[DatePickerPopoverViewController alloc] initWithCaller:self andKey:@"beginning"];
    UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:dppvc];

    popover.delegate = self;
    self.popoverController = popover;
    [popover release];

    [self.popoverController presentPopoverFromRect:[(UIButton *)sender frame]
                                            inView:self.view
                          permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}

- (IBAction)fromButtonHandler:(id)sender {
    dppvc = [[DatePickerPopoverViewController alloc] initWithCaller:self andKey:@"until"];
    UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:dppvc];

    popover.delegate = self;
    self.popoverController = popover;
    [popover release];

    CGRect senderFrameRect = [(UIButton *)sender frame];

    [self.popoverController presentPopoverFromRect:senderFrameRect
                                            inView:self.view
                          permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}


#pragma mark - UIPopoverControllerDelegate

//---called when the user clicks outside the popover view---
- (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController {

    // NSLog(@"popover about to be dismissed");
    return YES;
}

//---called when the popover view is dismissed---
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {

    // NSLog(@"popover dismissed");    
}

- (void)dismissPopover {
    if (popoverController != nil) {
        [popoverController dismissPopoverAnimated:YES];

        NSMutableArray *indexPaths = [[NSMutableArray alloc] init];
        int i;
        for (i = 0; i < [mtvcLabels count]; i++) {
            [indexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
        }

        [mtvcTableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:YES];
    }
}

- (void)dealloc {
    [mtvcSectionname release];
    [mtvcLabels      release];
    [mtvcData        release];

    [cell      release];

    [super dealloc];
}

Сбой происходит в main.m:

int main(int argc, char *argv[])
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    // crashes:
    int retVal = UIApplicationMain(argc, argv, nil, nil);        // <--

    [pool release];
    return retVal;
}

Я включил NSZombieEnabled, MallocStackLoggingNoComp и NSAutoreleaseFreedObjectCheckEnabled, но компилятор не дает мне больше информации, чем я написал.

Я провел весь день, пытаясь решить эту проблему, но безрезультатно.Любой намек в правильном направлении приветствуется!

Ответы [ 2 ]

0 голосов
/ 01 сентября 2011

Обычно я обращаюсь с этим, чтобы создать подкласс UITableViewCell для моих пользовательских ячеек.и использовать перо.Я создаю пользовательский init, который загружает ячейку из пера.следующим образом.

- (id)init
    {
    self = [[[[NSBundle mainBundle] loadNibNamed:@"NibName" owner:self options:nil] objectAtIndex:0] retain];
    if (self) 
        {
        // any further initialization
        }
    return self;
    }

в кончике установите класс ячейки для вашего нового класса.

затем, чтобы использовать вашу ячейку, выполните следующее.

  - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"CustomCell";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
  if (!cell)
      {
      cell = [[[CustomCell alloc] init] autorelease];
      }
  // setup your cell
return cell;
}

Вы обязательно должны использовать assign в своих свойствах делегата.

0 голосов
/ 01 сентября 2011

Я смог позаботиться об этой конкретной ошибке. Проблема заключалась в том, что cellRet в cellForRowAtIndexPath не было сохранено. Следующий фрагмент исправляет ошибку, упомянутую выше:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *cellRet;

    NSString *MyIdentifier = @"WeekdaySelectionWithPopoverCellController";

    cellRet = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];

    if (cellRet == nil) {
        [[NSBundle mainBundle] loadNibNamed:MyIdentifier owner:self options:nil];
        cellRet = self.cell;
        [cellRet retain];
    }

    // ...
}

Теперь, однако, я застрял с новой, похожей ошибкой. На этот раз он говорит:

*** -[CALayer release]: message sent to deallocated instance 0xc656d30

В следующем разделе содержится дополнительная информация о проблеме: "[Релиз CALayer]: сообщение отправлено освобожденному экземпляру" при отклонении контроллера модального представления

Я попытался изменить свойство контроллера представления popover на assign вместо retain, но это снова дало мне ошибку message sent to deallocated instance, на этот раз для контроллера представления popover.

Кто-нибудь с идеей? ТИА!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...