2012-05-11 18 views
0

私は簡単なチェックリストアプリを書いています。私は2つのUIViewControllerがあります。最初のチェックリストはUITableViewに表示されます。私はUIBarButtonItemを使用して新しいタスクを追加するためにスタックに2番目のビューをプッシュしています。すべてのタスクはアレイに保存されます。UITableViewでのセルの問題

すべては1つのことで節約できます。

編集モードに入ってテーブルビューからアイテムを削除すると、アイテムはテーブルビューとアレイから削除されます。この部分は正常に動作しているようです。しかし、アイテムを削除した後、新しいタスクを追加するためにバーのボタンアイテムをタップすると、問題が発生します。

私のNSLogsは、新しい項目が配列に追加されたことを通知しますが、テーブルビューに戻ると、新しい項目の代わりに削除された項目が表示されます。テーブルビューはデキューされたセルを再利用しているようです(不明)。

私は間違っていますか?

CLCheckListViewController.m

#import "CLCheckListViewController.h" 
#import "CLTaskFactory.h" 
#import "CLTaskStore.h" 
#import "CLAddTaskViewController.h" 

@implementation CLCheckListViewController 
{ 
    __weak IBOutlet UITableView *checkList; 
} 

- (id)init 
{ 
    self = [super init]; 
    if (self) { 
     // add five sample tasks 
     CLTaskFactory *task1 = [[CLTaskFactory alloc] init]; 
     [task1 setTaskName:@"Task 1"]; 
     [task1 setDidComplete:NO]; 
     [[CLTaskStore sharedStore] addTask:task1]; 

     CLTaskFactory *task2 = [[CLTaskFactory alloc] init]; 
     [task2 setTaskName:@"Task 2"]; 
     [task2 setDidComplete:NO]; 
     [[CLTaskStore sharedStore] addTask:task2]; 

     CLTaskFactory *task3 = [[CLTaskFactory alloc] init]; 
     [task3 setTaskName:@"Task 3"]; 
     [task3 setDidComplete:NO]; 
     [[CLTaskStore sharedStore] addTask:task3]; 

     CLTaskFactory *task4 = [[CLTaskFactory alloc] init]; 
     [task4 setTaskName:@"Task 4"]; 
     [task4 setDidComplete:NO]; 
     [[CLTaskStore sharedStore] addTask:task4]; 

     CLTaskFactory *task5 = [[CLTaskFactory alloc] init]; 
     [task5 setTaskName:@"Task 5"]; 
     [task5 setDidComplete:NO]; 
     [[CLTaskStore sharedStore] addTask:task5]; 
    } 
    return self; 
} 

- (void)viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 
    [checkList reloadData]; 
} 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    // create edit button 
    [[self navigationItem] setLeftBarButtonItem:[self editButtonItem]]; 

    // create title 
    [[self navigationItem] setTitle:@"Checklist"]; 

    // create add guest button 
    UIBarButtonItem *bbi = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(pushAddTask)]; 
    [[self navigationItem] setRightBarButtonItem:bbi]; 
} 

- (void)pushAddTask 
{ 
    CLAddTaskViewController *advk = [[CLAddTaskViewController alloc] init]; 
    [[self navigationController] pushViewController:advk animated:YES]; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    return [[[CLTaskStore sharedStore] allTasks] count]; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *CellIdentifier = @"Cell"; 

    UITableViewCell *cell = [checkList dequeueReusableCellWithIdentifier:CellIdentifier]; 

    if (!cell) { 
     cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 

     // put the tasks into the cell 
     [[cell textLabel] setText:[NSString stringWithFormat:@"%@", [[[CLTaskStore sharedStore] allTasks] objectAtIndex:[indexPath row]]]]; 

     // put the checkbox into the cell's accessory view 
     UIButton *checkBox = [UIButton buttonWithType:UIButtonTypeCustom]; 
     checkBox = [UIButton buttonWithType:UIButtonTypeCustom]; 
     [checkBox setImage:[UIImage imageNamed:@"checkbox.png"] forState:UIControlStateNormal]; 
     [checkBox setImage:[UIImage imageNamed:@"checkbox-checked.png"] forState:UIControlStateSelected]; 
     checkBox.frame = CGRectMake(0, 0, 30, 30); 
     checkBox.userInteractionEnabled = YES; 
     [checkBox addTarget:self action:@selector(didCheckTask:) forControlEvents:UIControlEventTouchDown]; 
     cell.accessoryView = checkBox; 
    } 
    return cell; 
} 

- (void)didCheckTask:(UIButton *)button 
{ 
    CGPoint hitPoint = [button convertPoint:CGPointZero toView:checkList]; 
    hitIndex = [checkList indexPathForRowAtPoint:hitPoint]; 

    task = [[[CLTaskStore sharedStore] allTasks] objectAtIndex:[hitIndex row]]; 

    if (task.didComplete) { 
     task.didComplete = NO; 
    } else { 
     task.didComplete = YES; 
    } 

    NSInteger taskCount = [[[CLTaskStore sharedStore] allTasks] count]; 
    for (int i = 0; i < taskCount; i++) { 
     NSLog(@"%@, status: %@", [[[CLTaskStore sharedStore] allTasks] objectAtIndex:i], [[[[CLTaskStore sharedStore] allTasks] objectAtIndex:i] didComplete][email protected]"YES":@"NO"); 
    } 

    // toggle checkbox 
    button.selected = !button.selected; 
} 

- (void)setEditing:(BOOL)editing animated:(BOOL)animated 
{ 
    [super setEditing:editing animated:animated]; 

    // set editing mode 
    if (editing) { 
     self.navigationItem.title = @"Edit Checklist"; 
     [checkList setEditing:YES]; 
    } else { 
     self.navigationItem.title = @"Checklist"; 
     [checkList setEditing:NO]; 
    } 
} 

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle 
              forRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    // remove task 
    if (editingStyle == UITableViewCellEditingStyleDelete) { 

     // remove task from CLTaskStore 
     task = [[[CLTaskStore sharedStore] allTasks] objectAtIndex:[indexPath row]]; 
     [[CLTaskStore sharedStore] removeTask:task]; 

     // remove guest from table view 
     [checkList deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 

     // reload table view 
     //[checkList reloadData]; 
    } 
} 

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath 
{ 
    [[CLTaskStore sharedStore] moveTaskAtIndex:[sourceIndexPath row] toIndex:[destinationIndexPath row]]; 
} 

@end 

CLAddTaskViewController.m

#import "CLAddTaskViewController.h" 
#import "CLTaskFactory.h" 
#import "CLTaskStore.h" 

@implementation CLAddTaskViewController 

    - (void)viewDidLoad 
    { 
     [[self navigationItem] setTitle:@"Add Task"]; 
    } 

    - (void)viewWillDisappear:(BOOL)animated 
    { 
     [super viewWillDisappear:animated]; 

     // clear first responder 
     [[self view] endEditing:YES]; 

     // create new task 
     CLTaskFactory *newTask = [[CLTaskFactory alloc] init]; 
     [newTask setTaskName:[newTaskName text]]; 

     // add new guest to RCGuestStore 
     [[CLTaskStore sharedStore] addTask:newTask]; 
    } 

    @end 

CLAddTaskFactory.m

#import "CLTaskFactory.h" 

@implementation CLTaskFactory 

@synthesize taskName; 

- (void)setDidComplete:(BOOL)dc 
{ 
    didComplete = dc; 
} 

- (BOOL)didComplete 
{ 
    return didComplete; 
} 

- (NSString *)description 
{ 
    // override the description 
    NSString *descriptionString = [[NSString alloc] initWithFormat:@"%@", taskName]; 
    return descriptionString; 
} 

@end 

CLAddTaskStore.m

#import "CLTaskStore.h" 
#import "CLTaskFactory.h" 
#import "CLCheckListViewController.h" 

@implementation CLTaskStore 

+ (id)allocWithZone:(NSZone *)zone 
{ 
    return [self sharedStore]; 
} 

+ (CLTaskStore *)sharedStore 
{ 
    static CLTaskStore *sharedStore = nil; 
    if (!sharedStore) { 
     sharedStore = [[super allocWithZone:nil] init]; 
    } 
    return sharedStore; 
} 

- (id)init 
{ 
    self = [super init]; 
    if (self) { 
     allTasks = [[NSMutableArray alloc] init]; 
    } 
    return self; 
} 

- (NSMutableArray *)allTasks 
{ 
    return allTasks; 
} 

- (void)addTask:(CLTaskFactory *)task 
{ 
    [allTasks addObject:task]; 
    NSLog(@"Task added: %@", task); 
} 

- (void)removeTask:(CLTaskFactory *)task 
{ 
    // remove the item for the deleted row from the store 
    [allTasks removeObjectIdenticalTo:task]; 

    NSInteger taskCount = [allTasks count]; 
    NSLog(@"Removed: %@, there are now %d remaining tasks, they are:", task, taskCount); 
    for (int i = 0; i < taskCount; i++) { 
     NSLog(@"%@, status: %@", [[[CLTaskStore sharedStore] allTasks] objectAtIndex:i], [[[[CLTaskStore sharedStore] allTasks] objectAtIndex:i] didComplete][email protected]"YES":@"NO"); 
    } 
} 

- (void)moveTaskAtIndex:(int)from toIndex:(int)to 
{ 
    if (from == to) { 
     return; 
    } 

    CLTaskFactory *task = [allTasks objectAtIndex:from]; 
    [allTasks removeObjectAtIndex:from]; 
    [allTasks insertObject:task atIndex:to]; 
} 

@end 

ご協力ありがとうございます!

答えて

1

テーブルビューはデキューセル、それはまったく同じものだ

に再利用しているようです。可能であれば、セルを再利用します。テーブルビューをスクロールさせるのに十分なアイテムがあれば、同じ問題が発生します。

-tableView:cellForRowAtIndexPath:では、dequeueReusableCellWithIdentifier:がセルを返すかどうかにかかわらず、指定された行インデックスの正しい内容を表示するようにセルを設定する必要があります。基本的には

は:

  • -dequeueReusableCellWithIdentifier:の場合はnilを返す、新しいセルを作成し、そこにあなたのチェックボックスのボタンを追加します。

  • は、次にセルのテキストと-dequeueReusableCellWithIdentifier:

1

ダレンが正しいから返されたこの新しいセルまたはセルのいずれかのボタンの状態を設定します。あなたがここにあなたのコードを見れば:

if (!cell) { 
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 

    // put the tasks into the cell 
    [[cell textLabel] setText:[NSString stringWithFormat:@"%@", [[[CLTaskStore sharedStore] allTasks] objectAtIndex:[indexPath row]]]]; 

    // put the checkbox into the cell's accessory view 
    UIButton *checkBox = [UIButton buttonWithType:UIButtonTypeCustom]; 
    checkBox = [UIButton buttonWithType:UIButtonTypeCustom]; 
    [checkBox setImage:[UIImage imageNamed:@"checkbox.png"] forState:UIControlStateNormal]; 
    [checkBox setImage:[UIImage imageNamed:@"checkbox-checked.png"] forState:UIControlStateSelected]; 
    checkBox.frame = CGRectMake(0, 0, 30, 30); 
    checkBox.userInteractionEnabled = YES; 
    [checkBox addTarget:self action:@selector(didCheckTask:) forControlEvents:UIControlEventTouchDown]; 
    cell.accessoryView = checkBox; 
} 

あなただけ追加説明のため

if (!cell) { 
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 
} 
// put the tasks into the cell 
[[cell textLabel] setText:[NSString stringWithFormat:@"%@", [[[CLTaskStore sharedStore] allTasks] objectAtIndex:[indexPath row]]]]; 

// put the checkbox into the cell's accessory view 
UIButton *checkBox = [UIButton buttonWithType:UIButtonTypeCustom]; 
checkBox = [UIButton buttonWithType:UIButtonTypeCustom]; 
[checkBox setImage:[UIImage imageNamed:@"checkbox.png"] forState:UIControlStateNormal]; 
[checkBox setImage:[UIImage imageNamed:@"checkbox-checked.png"] forState:UIControlStateSelected]; 
checkBox.frame = CGRectMake(0, 0, 30, 30); 
checkBox.userInteractionEnabled = YES; 
[checkBox addTarget:self action:@selector(didCheckTask:) forControlEvents:UIControlEventTouchDown]; 
cell.accessoryView = checkBox; 
+0

感謝するようにコードを変更し セルif(cell == nil)を設定します。非常に参考になりました。 – mySilmaril

関連する問題