在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()
答案 0 :(得分:0)
咄!
问题: 我使用.tag用于两个不同的目的。 其主要目的是索引UI控件以便重用。 但是,我正在重新分配UIButton。标签,按下按钮时要读取的数据。 因此,通过破坏.tag,无法再查找UIButton。
解: 我可以将数据放入由单元格(行)索引索引的数组中。然后: There's a cool answer here on how a UIButton delegate can lookup the cell index.