来自单元格的指针.当指针指向时,viewWithTag被设置为nil(0).标签设置



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

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

第二次调用cellForRowAtIndexPath():为第二个单元格分配UI控件,并且该单元格为空白。

稍后,需要显示2组控件,所以:第三次调用cellForRowAtIndexPath():"细胞。到最后一个按钮的contentView viewWithTag现在是0 (nil)!!!!它不再被分配。所以只显示第一组16个UI控件中的一些。然而,同一单元格内的第二组UI控件显示ok——它的UI控件仍然被分配。

这是内存管理问题吗?我是不是忘记了?我使用的是XCODE 5.0.2有自动ARC,因为如果我添加自动释放等,它会产生错误。

下面是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标签会将指向按钮的指针设置为0?IF .tag = 0;相反,问题仍然发生。如果.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()

废话!

问题:我使用。tag有两个不同的目的。它的主要目的是索引UI控件以便重用。但是,我在重新分配UIButton .tag的数据,当按钮被按下时读取。因此,通过破坏。tag, UIButton就不能再被查找了。

解决方案:我可以将数据放入由单元格(行)索引索引的数组中。然后:这里有一个关于UIButton委托如何查找单元格索引的很酷的答案

最新更新