如何正确更新表中部分中动态更改的行数(及其单元格内容)?

时间:2011-02-02 07:51:49

标签: iphone uiswitch uitableview

我正在尝试创建一个UITableViewController子类,通过我的应用程序设置向我提供UITableView。在重新加载有关UISwtitch状态的数据时遇到问题。

该表有3个部分:

  

第1节 - 不断一行

     

第2节 - 第一行中的UISwitch   使这一部分由1或3组成   行(取决于状态   UISwitch)

     

第3节 - 第一行中的UISwitch   使这一部分由1或3组成   行(取决于状态   UISwitch),但与另一个UISwitch   和其他行数据。

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

    switch ( section )
    {
        case 0:
            return 1;
            break;
        case 1:
            if ( limit_password_attempts )
                return 3;
            else 
                return 1;
            break;
        case 2:
            if ( lock_when_inactive )
                return 3;
            else 
                return 1;
            break;
        default:
            return 1;
            break;
    }  
}

第二和第三部分第一排的两个UISwitch-s分别改变BOOL

BOOL limit_password_attempts;
BOOL lock_when_inactive;

我的问题是当我在第二部分中转换UISwitch(用于exmpl)时,我希望我的第二部分再扩展2行,并填充新数据。它延伸,但新细胞看起来不像我想要的。第二行成为下一节中的第一行的副本(第一行带有UISwitch的第三节),如果第三节之前未扩展,则第三行返回正确,如果是,则该行变为第三部分第二行的副本。

所以我的单元格自定义看起来像这样,我猜错误就在这里。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *cell = nil;
    static NSString *EnabledCellIdentifier = @"Enabled";
    cell = [tableView dequeueReusableCellWithIdentifier:EnabledCellIdentifier];

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

        cell.detailTextLabel.enabled = YES;

        switch ( indexPath.section )
        {
            case 0: // section 1
                cell.textLabel.text = @"Banks settings";
                break;
            case 1: // section 2
            {
                switch ( indexPath.row )
                {
                    case 0:
                    {
                        cell.textLabel.text = @"Limit passwords attempts";
                        UISwitch* actSwitch = [[UISwitch alloc] initWithFrame: CGRectZero ];

                        [cell setEditingAccessoryView: actSwitch];

                        [actSwitch setTag: indexPath.section];
                        [actSwitch addTarget: self
                                      action: @selector(actSwitchChanged:) 
                            forControlEvents: UIControlEventValueChanged];

                        [self.view addSubview:actSwitch];
                        [actSwitch setOn:YES animated:NO];
                        [actSwitch setOn:NO animated:NO];

                        actSwitch.on = NO;
                        [cell addSubview: actSwitch];
                        cell.accessoryView = actSwitch;
                        [actSwitch release];
                        break;
                    }
                    case 1:
                        cell.textLabel.text = @"Lock after 3 atempts";
                        break;
                    case 2:
                        cell.textLabel.text = @"Lock for 30 min";
                        break;
                    default:
                        break;
                }
                break;
            }

            case 2: // section 3
            {
                switch ( indexPath.row )
                {
                    case 0:
                    {
                        cell.textLabel.text = @"Lock when inactive";
                        UISwitch* pactSwitch = [[UISwitch alloc] initWithFrame: CGRectZero ];

                        [cell setEditingAccessoryView: pactSwitch];

                        [pactSwitch setTag: indexPath.section];
                        [pactSwitch addTarget: self
                                      action: @selector(actSwitchChanged:) 
                            forControlEvents: UIControlEventValueChanged];

                        [self.view addSubview:pactSwitch];
                        [pactSwitch setOn:YES animated:NO];
                        [pactSwitch setOn:NO animated:NO];

                        pactSwitch.on = NO;
                        [cell addSubview: pactSwitch];
                        cell.accessoryView = pactSwitch;
                        [pactSwitch release];


                        break;
                    }
                    case 1:
                        cell.textLabel.text = @"Lock when inactive for 20 min";
                        break;
                    case 2:
                        cell.textLabel.text = @"Unlock key";
                        break;
                    default:
                        break;
                }
                break;
            }
            default:
                NSLog(@"%d", indexPath.section );
                break;
        }
    }
    return cell;
}

看起来有一些隐藏在我的数组中的行数据,这就是填充onec,而表控制器以某种方式更新表,具体取决于出现的行,只更新它们。在部分中添加行时,为什么会进行复制。这就像是一个阵列中的节点。我认为它必须向前推进细胞,但不仅仅是复制。 我是否要以某种方式删除行以使这种表更新? 我想我在这里错过了一些基本的东西。一些MVC概念?但这里是否真的有必要建立数据模型?为什么?如果是,那我该怎么做呢?

感谢您的回答。 祝你有个美好的一天。


这是在我的代码中。我只是没有在我的问题中写下来。 在UISwtitch切换后调用reloadData方法:

[pactSwitch setTag: indexPath.section];
[actSwitch addTarget: self
              action: @selector(actSwitchChanged:) 
    forControlEvents: UIControlEventValueChanged];

在actSwitchChanged方法中:

-(void) actSwitchChanged: (UISwitch*) pSwitch {

    if ( [pSwitch tag] == 1 ) //section 2
        limit_password_attempts = !limit_password_attempts ;
    else if ( [pSwitch tag] == 2 ) //section 3
        lock_when_inactive = !lock_when_inactive;
    [self.tableView reloadData];

}

所以reloadData确实会改变viewTable的内容,但它不是我想象的那样。

有什么想法吗?

3 个答案:

答案 0 :(得分:4)

数据模型总是存在......即使它只是UITableView调用的一堆if语句。我认为这种区别导致了这个问题。

您的布尔值代表您的基础数据模型。与数据模型的所有更改一样,您必须让表视图知道基础数据何时更改。

每当您更改一个布尔值时,请尝试添加以下呼叫。

[myTableViewController.tableView reloadData];

答案 1 :(得分:3)

你是对的,你实现了- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath的错误。如果您正在寻找简单的方法来实现具有不同布局的单元格而无需UITableViewCell的子类化,那么您需要,例如:

0)阅读this以深入理解UITableView编程

1)方法为每个布局返回一种单元格

- (NSString*)typeOfCellForIndexPath:(NSIndexPath*)indexPath {
    NSString *ret = @"CellWithoutSwitch";
    if(indexPath.section != 0 && idextPath.row == 0) {
        ret = @"CellWithSwitch";
    }
    return ret;
}

2)方法返回每种类型的单元格

- (UITableViewCell*)cellForType:(NSString*)aType {
    UITableViewCell *cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier: aType] autorelease];
    cell.detailTextLabel.enabled = YES;
    if ([aType isEqualToString:@"CellWithSwitch"]) {
        // just copy of your code
        // this does not need here
        cell.textLabel.text = @"Limit passwords attempts";
        // this needs but with CGRectMake(...) insted of CGRectZero
        UISwitch* actSwitch = [[UISwitch alloc] initWithFrame: CGRectZero ];
        // this does not need
        [cell setEditingAccessoryView: actSwitch];
        // this needs but for switch tag you should use #define SWITCH_TAG 777
        [actSwitch setTag: indexPath.section];
        // this does not need here
        [actSwitch addTarget: self
                      action: @selector(actSwitchChanged:) 
            forControlEvents: UIControlEventValueChanged];

        // wrong part of code
        [self.view addSubview:actSwitch];
        // this does not need here
        [actSwitch setOn:YES animated:NO];
        // wrong part of code
        [actSwitch setOn:NO animated:NO];

        actSwitch.on = NO;
        // ok
        [cell addSubview: actSwitch];
        // wrong part of code
        cell.accessoryView = actSwitch;
        // ok
        [actSwitch release];
    }
}

3)配置具有路径

的单元的方法
    - (void)cofigureCell:(UITableViewCell*)cell forIndexPath:(NSIndexPath*)indexPath {
        // just copy of your code
        switch ( indexPath.section )
        {
            case 0: // section 1
                cell.textLabel.text = @"Banks settings";
                break;
            case 1: // section 2
            {
                switch ( indexPath.row )
                {
                    case 0:
                    {
                        cell.textLabel.text = @"Limit passwords attempts";
                        /* this part of code replace with UISwitch* actSwitch = (UISwitch*)[cell viewWithTag:SWITCH_TAG];
                        UISwitch* actSwitch = [[UISwitch alloc] initWithFrame: CGRectZero ];

                        [cell setEditingAccessoryView: actSwitch];

                        [actSwitch setTag: indexPath.section];*/

                        [actSwitch addTarget: self
                                      action: @selector(actSwitchChanged:) 
                            forControlEvents: UIControlEventValueChanged];
                        /* all what you need now that cofigure an state of switch with limit_password_attempts variable - [actSwitch setOn:limit_password_attempts animated:NO];
// this is junk
                        [self.view addSubview:actSwitch];
                        [actSwitch setOn:YES animated:NO];
                        [actSwitch setOn:NO animated:NO];

                        actSwitch.on = NO;
                        [cell addSubview: actSwitch];
                        cell.accessoryView = actSwitch;
                        [actSwitch release];*/
                        break;
                    }
                    case 1:
                        cell.textLabel.text = @"Lock after 3 atempts";
                        break;
                    case 2:
                        cell.textLabel.text = @"Lock for 30 min";
                        break;
                    default:
                        break;
                }
                break;
            }

            case 2: // section 3
            {
                switch ( indexPath.row )
                {
                    case 0:
                    {
                        // look at previous configuration of switch
                        cell.textLabel.text = @"Lock when inactive";
                        UISwitch* pactSwitch = [[UISwitch alloc] initWithFrame: CGRectZero ];

                        [cell setEditingAccessoryView: pactSwitch];

                        [pactSwitch setTag: indexPath.section];
                        [pactSwitch addTarget: self
                                       action: @selector(actSwitchChanged:) 
                             forControlEvents: UIControlEventValueChanged];

                        [self.view addSubview:pactSwitch];
                        [pactSwitch setOn:YES animated:NO];
                        [pactSwitch setOn:NO animated:NO];

                        pactSwitch.on = NO;
                        [cell addSubview: pactSwitch];
                        cell.accessoryView = pactSwitch;
                        [pactSwitch release];


                        break;
                    }
                    case 1:
                        cell.textLabel.text = @"Lock when inactive for 20 min";
                        break;
                    case 2:
                        cell.textLabel.text = @"Unlock key";
                        break;
                    default:
                        break;
                }
                break;
            }
            default:
                NSLog(@"%d", indexPath.section );
                break;
        }
    }

4)实施最后一个方法

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *cell = nil;
    // get type for indexPath
    static NSString *EnabledCellIdentifier = [self typeOfCellForIndexPath:idextPath];
    cell = [tableView dequeueReusableCellWithIdentifier:EnabledCellIdentifier];

    if (cell == nil) 
    {
        // create a cell with needed type
        cell = [self cellForType:EnabledCellIdentifier];
    }

    // cofigure the cell
    [self cofigureCell:cell forIndexPath:indexPath];

    return cell;
}

答案 2 :(得分:0)

Gaj,谢谢你的回答。 它帮助了我,当我改变UISwitch条件时,表正确地重新加载。 但我必须更改uiswitch的标签,因为我确实需要区分我在actSwitchChanged方法中处理的UISwitch,以了解它是limit_password_attempts还是lock_when_inactive

我想将来不会出现问题?我的意思是,这里覆盖了SWITCH_TAG。 而且,为什么我需要#define SWITCH_TAG 777是不是有更好的方法来标记它?为什么777?

                 cell.textLabel.text = @"Limit passwords attempts";
                 UISwitch* actSwitch = (UISwitch*)[cell viewWithTag: SWITCH_TAG];
                 [actSwitch setTag: indexPath.section];
                 [actSwitch addTarget: self
                               action: @selector(actSwitchChanged:) 
                     forControlEvents: UIControlEventValueChanged];
                 [actSwitch setOn:limit_password_attempts animated:YES];

我还有更多问题:我的程序现在运行良好,但是,我不明白改变了什么。我添加了更多方法:cellForType:cofigureCell:forIndexPath:,但他们所做的一切在以前版本的cellForRowAtIndexPath:中实际上都是相同的。

那么..这里改变了什么让它正常工作? :)

相关问题