【问题标题】:pointer from cell.contentView viewWithTag is set to nil (0) when pointer.tag is set当 pointer.tag 设置时,来自 cell.contentView viewWithTag 的指针设置为 nil (0)
【发布时间】:2014-04-19 19:39:09
【问题描述】:

在 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(): 第 2 个单元格的 UI 控件已分配,此单元格为空白。

稍后,需要显示 2 组控件,所以: 第三次调用 cellForRowAtIndexPath(): 最后一个按钮的“cell.contentView viewWithTag”现在为 0(无)!!!它不再被分配。 因此仅显示第一组 16 个 UI 控件中的一部分。 但是,同一单元格中的第二组 UI 控件显示正常 - 它的 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 TAG 设置为 0? 如果 .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()

【问题讨论】:

    标签: ios iphone objective-c uitableview


    【解决方案1】:

    呃!

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-06
      • 2018-01-05
      • 2021-01-20
      • 1970-01-01
      • 2011-12-04
      • 1970-01-01
      相关资源
      最近更新 更多