How to update the dynamic change in the number of rows in a section in a UITable correclty (and its cell contents)?

I am trying to subclass UITableViewController by providing me with a UITableView with my application settings. I have a problem reloading UISwtitch status change data.

The table has 3 sections:

section 1 - one line constantly

section 2 - UISwitch in the first line making this section 1 or 3 lines (depending on the state of UISwitch)

section 3 - UISwitch in the first row making this section 1 or 3 rows (depending on the state of UISwitch), but with a different UISwitch and additional row data.

- (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;
    }  
}

These two UISwitch-s in the front rows of the second and third sections change BOOL, respectively

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, - , , , . . node . , , . , ? , . MVC? ? ? , ?

. .


. . reloadData UISwtitch:

[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
3

, - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath. UITableViewCell, :

0) 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;
}
+3

... if, UITableView. , .

. , , .

, .

[myTableViewController.tableView reloadData];
+4

, . , , UISwitch. uiswitch, , UISwitch actSwitchChanged, , 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];

And I have another question: my program now works well, but I do not understand what has changed. I added to other methods: cellForType:and cofigureCell:forIndexPath:, but everything they do was practically the same in the previous version cellForRowAtIndexPath:.

So ... what has changed here to make it work correctly? :)

0
source

Source: https://habr.com/ru/post/1789430/


All Articles