3

UITableViewController サブクラスを作成して、UITableView にアプリの設定を提供しようとしています。UISwtitch の状態が変化したときにデータをリロードするときに問題が発生しました。

テーブルには 3 つのセクションがあります。

セクション 1 - 常に 1 行

セクション 2 - このセクションを 1 行または 3 行で構成する最初の行の UISwitch (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;
    }  
}

2 番目と 3 番目のセクションの最初の行にある 2 つの UISwitch は、それぞれ BOOL を変更しています。

BOOL limit_password_attempts;
BOOL lock_when_inactive;

私の問題は、2 番目のセクションで UISwitch (exmpl 用) を切り替えると、2 番目のセクションがさらに 2 行拡張され、新しいデータが入力されることを期待することです。伸びますが、新しい細胞は私が望むようには見えません。2 番目の行は、次のセクション (3 番目のセクションの UISwitch を持つ行) の最初の行のコピーになり、3 番目のセクションが以前に拡張されていない場合、3 番目の行は正しく返されます。 3 番目のセクションから 2 番目の行のコピー。

したがって、セルのカスタマイズは次のようになります。エラーはここのどこかにあると思います。

- (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 の内容を変更しますが、期待どおりにはなりません。

何か案は?

4

3 に答える 3

4

データモデルは常に存在します...UITableViewが呼び出すifステートメントの集まりであっても。この区別が問題を引き起こしていると思います。

ブール値は、基礎となるデータモデルを表します。データモデルへのすべての変更と同様に、基になるデータが変更されたときにテーブルビューに通知する必要があります。

ブール値の1つを変更するたびに、次の呼び出しを追加してみてください。

[myTableViewController.tableView reloadData];
于 2011-02-02T18:10:48.163 に答える
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;
}
于 2011-02-03T22:26:18.877 に答える
0

ガイジ、答えてくれてありがとう。UISwitch の状態を変更すると、テーブルが正しくリロードされるようになりました。actSwitchChangedしかし、uiswitch のタグを変更する必要がありました。メソッドで扱っている UISwitch の種類を区別する必要があるためですlimit_password_attemptslock_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:.

それで..正しく動作させるためにここで何が変わったのですか?:)

于 2011-02-04T07:44:29.767 に答える