2011-11-14 5 views
0

私は、テーブルから1つの項目を選択するセクション化されたtableViewを持っています。彼らがアイテムを選択すると、アイテムの横にチェックが表示されます(UITableViewCellAccessoryCheckmarkを使用)。以前に選択した場合は、前に選択した行からチェックを削除する必要があります。セクション化されたテーブル内の行のaccessoryTypeを変更するユーザーが行を選択した後に表示

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 

    int newRow = [indexPath row]; 

    int oldRow = [lastIndexPath row]; 

    if (newRow != oldRow || newRow == 0) 
    { 

     UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath]; 
     newCell.accessoryType = UITableViewCellAccessoryCheckmark; 

     UITableViewCell *oldCell = [tableView cellForRowAtIndexPath: lastIndexPath]; 
     oldCell.accessoryType = UITableViewCellAccessoryNone; 

     [lastIndexPath release]; 
     lastIndexPath = indexPath; 
    } 

    [tableView deselectRowAtIndexPath:indexPath animated:YES]; 

} 

lastIndexPath.hファイルで私的に宣言されています。ここで私が使用していたコードがあります。

このコードは、セクション化されていない小さなリストに最適です。しかし、セクション化された大きなテーブルでは、他のセクションの行にランダムなチェックマークが付けられます。ほとんどの場合、cellForRowAtIndexPathがindexPathのセクションを無視しているようです。

最小のセクションの行数よりも大きい行を選択すると、コードがクラッシュします。ここで

はcellForRowAtIndexPathのコードです:あなたがここに持っている

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    NSUInteger section = [indexPath section]; 

    NSUInteger row = [indexPath row]; 

    NSString *key = [keys objectAtIndex:section]; 

    NSArray *itemSection = [items objectForKey:key]; 

    static NSString *SectionsTableIdentifier = @"SectionsTableIdentifier"; 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SectionsTableIdentifier]; 

    if (cell == nil) { 

     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:SectionsTableIdentifier] autorelease]; 

    } 
    NSArray *rowLabel = [itemSection objectAtIndex:row]; 

    cell.textLabel.text = [rowLabel objectAtIndex:1]; 

    NSString *detText = [rowLabel objectAtIndex:0]; 

    detText = [detText stringByAppendingString:@"   $"]; 

    detText = [detText stringByAppendingString:[rowLabel objectAtIndex:2]]; 

    cell.detailTextLabel.text = detText; 

    return cell; 
} 
+0

は、 'cellForRowAtIndexPath:'のコードを参照する必要があります。私は、あなたがデキューしているセルと再利用識別子( 'cellForRowAtIndexPath:'のデフォルト実装)を使用していると仮定しています。その場合、セルを作成するためのコードは、マークされたセルをテンプレートとして再利用して新しいセルを作成します。この問題を解決するには、いくつかのことができます: "cellForRowAtIndexPath:'で毎回新しいセルを作成するか、 ''各セルへの参照を保持し、 '' cellForRowAtIndexPath: ''の呼び出しを回避する。 – ColdLogic

+0

はい - これはランダムなチェックマークの最初の問題を解決することができますが、最小のセクションの行数よりも大きい行を選択すると、クラッシュの第2の問題が解決されるとは思われません。ここにcellForRowAtIndexPathコード: –

+0

あなたはコメントにそのコードを投稿することはできません。元の投稿に追加する – ColdLogic

答えて

0

一つの問題は、あなたがlastIndexPathでindexPathを保存している方法です。 lastIndexPathに保存するindexPathを保持する必要があります。このメソッドに渡されたindexPathはオートレリースされているため、保持しないと、あなたの下からリリースされる可能性が高くなります。これはあなたのクラッシュを引き起こす可能性があります。

0

これはおそらくあなたが探しているものです。私はこれを私のアプリの一つのために開発しました。楽しい ! (答えがある場合はマークしてください) また、ARCを使用しているので、保持したり解放したりすることはできません。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    /* 
    1. First we get the indexPath from the prior priorSelectedRowInteger and priorSelectedSectionInteger ivars. Note: we could use a single indexPath ivar, but we separate them into row and section here for clarity. 
    2. Then we reset the selectedRowInteger ivar to the currently selected row. This must be done before any rows are reloaded. 
    3. Then we reload only the two rows at the concerned index paths, as we have captured the indexPath of the prior selected row and the method gives us the new one. We could just simply reload the table here with [self.tableView reloadData], but it would not be animated and not as smooth. 

    */ 
    NSIndexPath *priorSelectedIndexPath = [NSIndexPath indexPathForRow:priorSelectedRowInteger inSection: priorSelectedSectionInteger]; 
    // Now that we have the priorSelectedIndexPath, we save the new one for the next round. 
    self.priorSelectedRowInteger = indexPath.row; 
    self.priorSelectedSectionInteger = indexPath.section; 

    // For a changing tableView, check to make sure the priorIndexPath is still valid before trying to reload the prior row. 
    // NSLog(@"priorSelectedIndexPath %@", priorSelectedIndexPath); 
    if ((tableView.numberOfSections >= priorSelectedIndexPath.section+1) && ([tableView numberOfRowsInSection:priorSelectedIndexPath.section] >= priorSelectedIndexPath.row+1)) { 
    NSArray *thePriorIndexPathArray = [NSArray arrayWithObject:priorSelectedIndexPath]; 
    [self.tableView reloadRowsAtIndexPaths:thePriorIndexPathArray withRowAnimation:UITableViewRowAnimationFade]; 
} 


    // Reload only the selected indexPath - necessary to update the text colors etc. 
    NSArray *theIndexPathArray = [NSArray arrayWithObject:indexPath]; 
    [self.tableView reloadRowsAtIndexPaths:theIndexPathArray withRowAnimation:UITableViewRowAnimationFade]; 
} 
関連する問題