0

我正在尝试在我的cellForRowAtIndexPath方法中向单元格添加一个按钮。那行得通,但我似乎每次更新单元格时都添加一个按钮(发现这个是因为我更新了错误的屏幕位置,并且我有 2 个既可以工作又可以单击的按钮)。

何时是分配和释放UIButton添加到单元格的正确时间?当然我不能在结束时释放按钮cellForRowAtIndexPath- 那会破坏按钮对象,不是吗?到目前为止,我发现的所有带有添加到单元格的按钮的片段似乎都在实例化新UIButton对象,cellForRowAtIndexPath其中让我有些困惑..

4

3 回答 3

1

通常,您尝试通过检索单元格dequeueReusableCellWithIdentifier,如果返回nil,则创建一个UITableViewCell. 只有在这种情况下,您才需要创建按钮。否则按钮已经存在。

就何时释放而言,您通常会 (a) 创建按钮;(b) 将其添加为单元格的子视图;(c) 如果是 ARC 代码,那么您将在那里释放按钮。因为它是作为子视图添加的,所以保留计数仍为 1,因此在单元格本身被释放之前不会被释放(你永远不必担心......iOS 会为你做到这一点)。

因此你cellForRowAtIndexPath会是这样的:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    UIButton *button;
    if (cell == nil) 
    {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];

        button = [[UIButton alloc] initWithFrame:buttonFrame];
        [button setTag:kButtonTag]; // if you need to do any reconfiguring of the button, it may be useful to set a tag
        // do additional button configuration
        [[cell contentView] addSubview:button];
        [button release]; // only needed if non-ARC
    }
    else
    {
        // if you need to reconfigure the button, you can grab it from the dequeued cell
        // obviously if you don't need to reconfigure it, you don't need to retrieve it again
        button = (UIButton*)[[cell contentView] viewWithTag:kButtonTag];
    }

    // complete the configuration of the cell

    return cell;
}
于 2012-06-30T05:34:44.757 回答
1

有几件事:

  1. 按钮出现在别处是因为您对不同类型的单元格使用相同的单元格标识符。每种类型的单元格都应该有自己的标识符。

  2. 在按钮消失方面,我不知道为什么会发生这种情况reloadRowsAtIndexPaths,但是如果您将按钮移动到其他子视图的前面,您将不会丢失它。

  3. 你可能想要autorelease你的 UITextField。(与 NSString 中的相同titleForHeaderInSection。)

无论如何,cellForRowAtIndexPath变成这样:

#define kTextFieldTag 100
#define kButtonFieldTag 101

//-----------------------------------------------------------------------------------------
// cellForRowAtIndexPath
//-----------------------------------------------------------------------------------------
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *cellIdentifier;
    UITableViewCell *cell;

    // Configure the cell...
    switch( [indexPath section] ) 
    {
        case WORKSHEET_SECTION_CLIENT: 
            cellIdentifier = @"CellClient";

            cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

            if (cell == nil) 
            {
                cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
            }

            cell.textLabel.text = clientName;
            cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;      
            break;

        case WORKSHEET_SECTION_PERIOD: 
        {
            UIButton *myButton1;

            cellIdentifier = @"CellPeriod";

            cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

            if (cell == nil) 
            {
                cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];

                // Don't need UIButton alloc because method below does it for us..
                myButton1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
                myButton1.tag = kButtonFieldTag;

                CGRect cellFrame = [self.tableView rectForRowAtIndexPath:indexPath];

                int nButtonWidth  = 80;
                int nButtonHeight = 30;
                int nActualCellWidth = cellFrame.size.width - 40;
                int nButtonDeltaX = ( nActualCellWidth      - nButtonWidth  ) / 2;
                int nButtonDeltaY = ( cellFrame.size.height - nButtonHeight ) / 2;
                myButton1.frame = CGRectMake( nButtonDeltaX, nButtonDeltaY, nButtonWidth, nButtonHeight );      

                [myButton1 setTitle:@"OK" forState:UIControlStateNormal];

                // PDS: Add delaget for stopwatch clicking..
                [myButton1 addTarget:self action:@selector(buttonClickedStopWatch:) forControlEvents:UIControlEventTouchUpInside];  

                [cell.contentView addSubview:myButton1];      
            }
            else
            {
                myButton1 = (UIButton *)[[cell contentView] viewWithTag:kButtonFieldTag];
            }

            cell.textLabel.text = timeElapsed;
            cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;   
            [[cell contentView] bringSubviewToFront:myButton1];

            break;      
        }

        case 2:
            cellIdentifier = @"Cell2";

            cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

            if (cell == nil) 
            {
                cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
            }

            cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
            cell.textLabel.text = @"Amount $130";
            break;      

        case 3:
        {
            cellIdentifier = @"Cell3";

            cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
            UITextField *myTextField;            

            if (cell == nil) 
            {
                cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];

                myTextField = [[[UITextField alloc] initWithFrame:CGRectMake(20,10,125,25)] autorelease];
                [myTextField setTag:kTextFieldTag];
                myTextField.adjustsFontSizeToFitWidth = NO;
                myTextField.backgroundColor = [UIColor clearColor];
                myTextField.autocorrectionType = UITextAutocorrectionTypeNo;
                myTextField.autocapitalizationType = UITextAutocapitalizationTypeWords;
                myTextField.textAlignment   = UITextAlignmentLeft;
                myTextField.keyboardType    = UIKeyboardTypeDefault;
                myTextField.returnKeyType   = UIReturnKeyDone;
                myTextField.clearButtonMode = UITextFieldViewModeNever;
                //      myTextField.delegate = self;
                myTextField.font = [UIFont systemFontOfSize:14];

                [cell addSubview:myTextField];
            }
            else
            {
                myTextField = (UITextField *)[[cell contentView] viewWithTag:kTextFieldTag];
            }

            // note, theoretically, you could blow away anything that the user typed here
            [myTextField setPlaceholder:@"Type Data Here"];          

            cell.accessoryType = UITableViewCellAccessoryNone;

            cell.textLabel.font = [UIFont systemFontOfSize:14];
            cell.textLabel.numberOfLines = 0;
            break;

        }

        default:
            cellIdentifier = @"CellDummy";

            cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

            if (cell == nil) 
            {
                cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
            }

            cell.textLabel.text = @"Dummy";
            break;

    }

    return cell;
}

就个人而言,我可能会将其拆分为单独的方法,但这取决于您。

于 2012-07-02T13:37:13.947 回答
0

理想情况下,在添加之后UIButtonUITableViewCell可以释放它。因为在该按钮之后将出现在您的单元格中。

于 2012-06-30T05:13:43.753 回答