当设置pointer.tag时,来自cell.contentView viewWithTag的指针设置为nil(0)

时间:2014-03-14 13:23:52

标签: ios iphone objective-c uitableview

在UITableViewCell的委托中,当我得到一个指向以前分配的UIButton的指针时...... UIButton * PWR_RX_tracking_button =(UIButton *)[cell.contentView viewWithTag:BASE_UIBUTTON_TAG + cell_UIButton_index ++]; ...如果我这样做,这个指针将休息为nil(0): PWR_RX_tracking_button.tag = 0; ......或将其设置为任何值。

我显示一个显示2个单元格的UITableView。 第一次调用cellForRowAtIndexPath(), 分配第一个单元格的UI控件,并显示一组16个UI控件(图像,标签,文本,一些按钮)。

第二次调用cellForRowAtIndexPath(): 分配了第二个单元格的UI控件,此单元格为空白。

稍后,需要显示2组控件,因此: 第三次调用cellForRowAtIndexPath(): 最后一个按钮的“cell.contentView viewWithTag”现在为0(零)!它不再分配。 所以只显示第一组16个UI控件中的一些。 但是,同一单元格中的第二组UI控件显示正常 - 其UI控件仍然已分配。

这是内存管理问题吗?我不能以某种方式保留? 我正在使用XCODE 5.0.2 有自动ARC,因为如果我添加autorelease等它会产生错误。

这是cellForRowAtIndexPath()胆量:

.m文件...............

UITableView * device_charge_tableView [TOTAL_TX_CHANNELS];

 -(void)init_table
 {
            device_charge_tableView[ channel ] = [[UITableView alloc]initWithFrame:tableFrame style:UITableViewStylePlain];

            device_charge_tableView[ channel ].rowHeight = device_charge_row_height;
            device_charge_tableView[ channel ].sectionFooterHeight = 0;
            device_charge_tableView[ channel ].sectionHeaderHeight = 0;
            device_charge_tableView[ channel ].scrollEnabled = YES;
            //new_system_device_tableView.showsVerticalScrollIndicator = YES;
            //      device_charge_tableView[ channel ].userInteractionEnabled = YES;
            device_charge_tableView[ channel ].bounces = YES;

            device_charge_tableView[ channel ].delegate = self;
            device_charge_tableView[ channel ].dataSource = self;
            device_charge_tableView[ channel ].allowsSelection = NO;
            device_charge_tableView[ channel ].tag = channel;

            //  device_charge_tableView[ channel ].autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
            charge_record_index = expected_charge_index = 0;
            [device_charge_tableView[ channel ]  reloadData];               // display channel's TableView
            [[self view] addSubview:   device_charge_tableView[ channel ]];
 }


 -(void)redisplay
 {
     ...
     [device_charge_tableView[ 0 ]  reloadData];    
     ...
 }




- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{

            return 2;      // add 1 row for a nice looking blank cell at end
}



- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
        return device_charge_row_height;  
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
        ...
            NSString *CellIdentifier = [NSString stringWithFormat:@"%s_%d",device_off_table ? "OFF" : "CHG", table_cell_index];
            UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

            if (cell == nil)
            {
                cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier: CellIdentifier];
                /* Though it's UITableViewCellStyleDefault, the three defaults (image, label, detail label) are nil
                if not set. */      
                // UI controls must be preset for re-use, to prevent memory leak:  
                // Allocate contiguous range of tags for each type of UI control for all devices, in this cell, once per boot:
                    int instance;
                    for(  instance=0; instance < total_cell_UILabels; ++instance )
                    {
                        ///////////////   A L L O C A T E   C E L L   L A B E L S   ///////////////

                        UILabel*   cell_UILabel = [[UILabel alloc] initWithFrame: CGRectZero];  // allocate next UI control
                        [cell.contentView addSubview: cell_UILabel ];                           // add it permanently to the cell
                        cell_UILabel.tag = BASE_UILABEL_TAG + instance;                         // assign unique ID for later lookup
                        if( dbg_cell )      printf( " tag_%d ", cell_UILabel.tag );
                    }
                    for(  instance=0; instance < total_cell_UITextViews; ++instance )
                    {
                        ///////////////   A L L O C A T E   C E L L   T E X T V I E W S   ///////////////

                        UITextView*   cell_UITextView = [[UITextView alloc] initWithFrame: CGRectZero];
                        [cell.contentView addSubview: cell_UITextView ];
                        cell_UITextView.tag = BASE_UITEXTVIEW_TAG + instance;
                        if( dbg_cell )      printf( " tag_%d ", cell_UITextView.tag );
                    }
                    for(  instance=0; instance < total_cell_UIImageViews ; ++instance )
                    {
                        ///////////////   A L L O C A T E   C E L L   I M A G E V I E W S   ///////////////

                        UIImageView*   cell_UIImageView = [[UIImageView alloc] initWithFrame: CGRectZero];
                        [cell.contentView addSubview: cell_UIImageView ];
                        cell_UIImageView.tag = BASE_UIIMAGEVIEW_TAG + instance;
                        if( dbg_cell )      printf( " tag_%d ", cell_UIImageView.tag );
                    }
                    // Allocate invisible buttons:
                        for(  instance=0; instance < total_cell_UIButtons ; ++instance )
                        {
                            ///////////////   A L L O C A T E   C E L L   B U T T O N S   ///////////////

                            UIButton*   cell_UIButton = [UIButton  buttonWithType: UIButtonTypeCustom];
                            [cell_UIButton setTitle:@"" forState:UIControlStateNormal];
                            cell_UIButton.frame = CGRectZero;

                            [cell.contentView addSubview: cell_UIButton ];
                            cell_UIButton.tag = BASE_UIBUTTON_TAG + instance;
                            if( dbg_cell )      printf( " tag_%d ", cell_UIButton.tag );
                        }
                if( dbg_cell )      printf("\n");
            }

        ...

        for(;;)     // LOOP for times, to display 4 sets of UI controls next to each other:
        {

                // Get pointers to all possible UI controls of this UITableViewCell:
                    UILabel* PWR_RX_title                       = (UILabel*)    [cell.contentView viewWithTag: BASE_UILABEL_TAG     +    cell_UILabel_index++ ];
                    UILabel* PWR_RX_footer                      = (UILabel*)    [cell.contentView viewWithTag: BASE_UILABEL_TAG     +    cell_UILabel_index++ ];    
                    UILabel* PWR_RX_voltage                     = (UILabel*)    [cell.contentView viewWithTag: BASE_UILABEL_TAG     +    cell_UILabel_index++ ];
                    UILabel* PWR_RX_rssi                        = (UILabel*)    [cell.contentView viewWithTag: BASE_UILABEL_TAG     +    cell_UILabel_index++ ];
                    UILabel* PWR_RX_power                       = (UILabel*)    [cell.contentView viewWithTag: BASE_UILABEL_TAG     +    cell_UILabel_index++ ];
                    UILabel* client_type_label                  = (UILabel*)    [cell.contentView viewWithTag: BASE_UILABEL_TAG     +    cell_UILabel_index++ ];
                    UILabel* battery_percent_text               = (UILabel*)    [cell.contentView viewWithTag: BASE_UILABEL_TAG     +    cell_UILabel_index++ ];
                    UILabel* client_device_title                = (UILabel*)    [cell.contentView viewWithTag: BASE_UILABEL_TAG     +    cell_UILabel_index++ ];
                    UITextView* PWR_RX_cover_box                = (UITextView*) [cell.contentView viewWithTag: BASE_UITEXTVIEW_TAG  +    cell_UITextView_index++ ]; 
                    UIImageView* device_icon_UIImageView        = (UIImageView*)[cell.contentView viewWithTag: BASE_UIIMAGEVIEW_TAG +    cell_UIImageView_index++ ];
                    UIImageView* energy_glow_UIImageView        = (UIImageView*)[cell.contentView viewWithTag: BASE_UIIMAGEVIEW_TAG +    cell_UIImageView_index++ ];
                    UIImageView* battery_level_icon             = (UIImageView*)[cell.contentView viewWithTag: BASE_UIIMAGEVIEW_TAG +    cell_UIImageView_index++ ];
                    UIButton* PWR_RX_charge_button              = (UIButton*)   [cell.contentView viewWithTag: BASE_UIBUTTON_TAG    +    cell_UIButton_index++ ];       
                    UIButton* invisible_drag_button             = (UIButton*)   [cell.contentView viewWithTag: BASE_UIBUTTON_TAG    +    cell_UIButton_index++ ];       
                    UIButton* PWR_RX_tracking_button            = (UIButton*)   [cell.contentView viewWithTag: BASE_UIBUTTON_TAG    +    cell_UIButton_index++ ];   

...

                PWR_RX_tracking_button.frame = CGRectMake   (x,y + h * 2/3, w, h/3);    // lower quarter of icon        !!! NORMAL

                        PWR_RX_tracking_button.tag = area_device_status[ channel ][ PWR_RX_status_index ].serno_value;



                    >>>>>>>>>>>>>  ERROR IS:  <<<<<<<<<<<<<<<<
                    1ST TIME PWR_RX_tracking_button IS OKAY.
                    2ND TIME, PWR_RX_tracking_button = 0  !!!!!!!!!!!!!!!!!!!!!

为什么在单元格中将UIBUTTON TAG设置为按钮到0? IF .tag = 0; INSTEAD,问题仍然存在。 如果.tag =被评论出来,问题就会消失。

                        [PWR_RX_tracking_button addTarget:self 
                                   action:@selector( delegate_tracking_button: )
                         forControlEvents: UIControlEventTouchUpInside ];


            ...


            ++cell_record_index;        // select next device record
            ++device_per_row_index;     // select next display device of row
            if( device_per_row_index < devices_per_cell )   // another device to display on this row?
                continue;   // GO DISPLAY NEXT SET OF THE 4 SETS OF UI CONTROLS
            else
                break;      // ALL SETS have been shown
        }   

        // CHECK FOR DESIGN ERROR, IF UI control array limited exceeded:
        if(     cell_UILabel_index > total_cell_UILabels        + UI_controls_per_cell * table_cell_index 
            ||  cell_UIImageView_index > total_cell_UIImageViews    + UI_controls_per_cell * table_cell_index 
            ||  cell_UITextView_index > total_cell_UITextViews      + UI_controls_per_cell * table_cell_index 
            ||  cell_UIButton_index > total_cell_UIButtons      + UI_controls_per_cell * table_cell_index )
        {
            printf("\n cell_UILabel_index cell_UIImageView_index cell_UITextView_index cell_UIButton_index  %d %d %d %d", cell_UILabel_index, cell_UIImageView_index, cell_UITextView_index, cell_UIButton_index );
            printf("\n total_cell_UILabels total_cell_UITextViews total_cell_UIImageViews  %d %d %d %d", 
                total_cell_UILabels, total_cell_UITextViews, total_cell_UIImageViews, total_cell_UIButtons );
            printf("   <<< MAX EXCEEDED!!  HALTED.");
            for(;;)  sleep(1);
        }
        save_record_index( cell_record_index, expected_cell_index, device_off_table );
                                                                                                                            if( dbg_cell )      printf(" HHH \n");
        return cell;
}   // cellForRowAtIndexPath()

1 个答案:

答案 0 :(得分:0)

咄!

问题: 我使用.tag用于两个不同的目的。 其主要目的是索引UI控件以便重用。 但是,我正在重新分配UIButton。标签,按下按钮时要读取的数据。 因此,通过破坏.tag,无法再查找UIButton。

解: 我可以将数据放入由单元格(行)索引索引的数组中。然后: There's a cool answer here on how a UIButton delegate can lookup the cell index.