1

UITableViewのヘッダーにUISwitchを追加および管理するための最良のアプローチを見つけようとしています。これまで、テーブルでUISwitchを使用するのに最適な方法に関するいくつかのリンクを読みました:ここここ、およびここ。これらのリンクは、セルでUISwitchを使用しているのに対し、ヘッダーのカスタムUIViewで使用していることを示しています。そうは言っても、これらのオブジェクトを管理するためにタグを使用したいのですが、viewWithTagアプローチが機能しない理由を理解できません。

補足:実行時にUISwitchをNSMutableArrayに入れてそのように管理することはできましたが、それほど冗長ではなく、配列の境界違反/インデックスを管理したり、nilリストをチェックしたりすることはできませんでした...また、IBOutletsを使用してこれをどのように行うかは私にはわかりません。これが私がタグアプローチを試みている理由です。

私の目標は、スイッチを使用して各セクションの行を折りたたんだり展開したりすることです。そのため、viewForHeaderInSectionで返すUIViewにサブビューとしてUISwitchをタグ付けして追加することを考えました。その後、セルを折りたたむためにロジックを実行する必要があるときに、それらを再参照します。さらに、実行時に1つ以上のセクションを持つ可能性があるため、タグ番号をハードコーディングすることは実用的ではありません。そのメソッドのコードは次のとおりです。

仮定:

#define kSwitchTagRange 2000
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{    
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.tableView.bounds.size.width, 44)];

    // Add UISwitches and ensure that UISwitch doesn't already exist for this section...
    UISwitch *switchView = (UISwitch*)[self.tableView viewWithTag:(kLayerSwitchTagRange + section)];

    if (switchView == nil) {

        // Create switch
        switchView = [[UISwitch alloc] init];
        double xOffset = self.tableView.bounds.size.width - switchView.frame.size.width;
        switchView.frame = CGRectMake(xOffset,
                                      7,
                                      switchView.frame.size.width,
                                      switchView.frame.size.height);

        [switchView addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged];

        // Should we tag the switch view?
        switchView.tag = kSwitchTagRange + section;
    }

    // Add switch as subview
    [view addSubview:switchView];    

    return view;
}

switchChangedの場合:テーブルのデータをリロードするだけです:

- (void)switchChanged:(id)sender {

     [self.tableView reloadData];
}

最後に、テーブルのデータが再作成されるときに、UISwitchを取得してオン/オフ状態を判断しようとします。次に、セクションの行数がオフの場合は0を返し、オンの場合は他の数を返します。

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

    NSInteger rowCount = 0;

    UISwitch *switchView = (UISwitch*)[self.view viewWithTag:(kSwitchTagRange + section)];

    if (switchView != nil && switchView.isOn == NO)
    {
        rowCount = 0;

    }
    else
    {
        // Row count is something other than 0
        rowCount = 3;
    }

    return rowCount;
}

残念ながら、このswitchViewは常にnilです。

いくつか推測がありますが、なぜこれが起こっているのか判断できません。

  • 推測1:テーブルのデータが再ロードされたときに、必要なスイッチが追加されたUIViewの割り当てが解除されます。メモリに存在しないため、タグで検索しても見つかりません。
  • 推測2:UISwitchをビューオブジェクトに誤って追加しています(多くの例で、オブジェクトがUITableViewCellのcontentViewに追加されているのを見てきましたが、viewForHeaderInSection:メソッドでUIViewを送り返しているので、それらがわかりませんここに例が適用されます。addSubviewは任意のオブジェクトをツリーに追加する必要があります。

上記のviewWithTagメソッドがnilを返す理由を誰かに教えてもらえますか?私は推測#1に傾倒していますが、カスタムヘッダーUIViewの割り当てがいつでも解除されることを示すドキュメントは見つかりませんでした。セルは再利用されますが、セクションヘッダーはどうですか?

最後に、私はこの投稿を読みました。タグの使用に関する推奨事項は理にかなっていますが、タグのアプローチはまったく嫌いなようです。タグの使用が面倒でなく、インテリジェントに使用されている場合は、タグを使用してみませんか?タグ機能が利用できるのはなぜですか?

本当に、私の場合、viewWithTagメソッドがnilを返す理由を知りたいだけです。

乾杯!

4

2 に答える 2

1

あなたの viewWithTag が常に nil を返す理由はわかりませんが、ある時点でビューの割り当てが解除されるという事実に関係している可能性があると思います。

ただし、タグは引き続き機能して目的を実行できますが、スイッチの値を追跡するモデル オブジェクトにプロパティまたはキーが必要です。タグを使用して、アクション メソッドでスイッチがどのセクションにあるかを示し、モデルを適切に更新できます。これが私がしたことです。私のモデルは、キー「rowData」の値がそのセクションのすべてのデータを含む配列であり、キー「switchValue」の値がスイッチの状態を表す NSNumber、0 または 1 である辞書の配列です。 . したがって、私のデータは次のようになります。

2012-11-28 22:50:03.104 TableWithSwitchesInHeaderView[3592:c07] (
        {
        rowData =         (
            One,
            Two,
            Three,
            Four
        );
        switchValue = 1;
    },
        {
        rowData =         (
            Red,
            Orange,
            Yellow,
            Green,
            Blue,
            Violet
        );
        switchValue = 1;
    },
)

これは、関連するテーブル ビュー デリゲートとデータ ソース メソッドにあるものです。

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return self.theData.count;
}

-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.tableView.bounds.size.width, 44)];
    UISwitch *switchView = [[UISwitch alloc] init];
    double xOffset = self.tableView.bounds.size.width - switchView.frame.size.width;
    switchView.frame = CGRectMake(xOffset,7,switchView.frame.size.width,switchView.frame.size.height);
    [switchView addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
    switchView.tag = kSwitchTagRange + section;
    switchView.on = [[[self.theData objectAtIndex:switchView.tag - 101] valueForKey:@"switchValue"] boolValue];
    [view addSubview:switchView];
    return view;
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    return 50;
}

- (void)switchChanged:(UISwitch *)sender {
    NSMutableDictionary *dict = [self.theData objectAtIndex:sender.tag - 101];
    [dict setValue:[NSNumber numberWithBool:sender.isOn] forKey:@"switchValue"];
    [self.tableView reloadData];
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    BOOL switchValue = [[self.theData[section] valueForKey:@"switchValue"] boolValue];
    if (switchValue) {
        return [[self.theData[section] valueForKey:@"rowData"] count];
    }else{
        return 0;
    }

}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    cell.textLabel.text = [[self.theData[indexPath.section]valueForKey:@"rowData"]objectAtIndex:indexPath.row] ;
    return cell;
}

私の kSwitchTagRange は #101 として定義されていました。このコードは、スイッチがオフになっている任意のセクションで行を折りたたむ (実際にはすべての行を削除する) ように機能しました。

于 2012-11-29T07:03:13.440 に答える
0

ここの投稿から、viewForHeaderInSectionによって返されるUIViewは割り当てが解除されており、再利用するのではなく、再作成する必要があるようです(UISwitchを含むすべてのサブビューも同様です)。Appleは、セルよりもセクションヘッダーがはるかに少ないと想定しているため、セクションヘッダーを取得するための再利用メカニズムを提供していなかったと思います。@rdelmarによって提案されたデータにバインドされたアプローチは、このシナリオには意味があるようです。

于 2012-11-29T18:06:06.090 に答える