0

我正在编写一个简单的清单应用程序。我有两个 UIViewControllers。第一个在 UITableView 中显示清单。我正在使用 UIBarButtonItem 将第二个视图推送到堆栈上以添加新任务。所有任务都保存在一个数组中。

除了一件事,一切都很好。

如果我进入编辑模式并从表视图中删除一个项目,该项目将从表视图和数组中删除——这部分似乎工作正常。但是,删除项目后,如果我点击栏按钮项目添加新任务,我会遇到问题。

我的 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]?@"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]?@"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

谢谢你的帮助!

4

2 回答 2

1

表视图似乎正在重用出队的单元格

这正是它的作用;它尽可能重复使用单元格。如果您有足够的项目使表格视图滚动,您也会看到同样的问题。

-tableView:cellForRowAtIndexPath:您必须始终设置单元格以显示给定行索引的正确内容,无论是否dequeueReusableCellWithIdentifier:返回单元格。

基本上:

  • 如果-dequeueReusableCellWithIdentifier:返回 nil,则创建一个新单元格并将您的复选框按钮添加到其中。

  • 然后在这个新单元格或从返回的单元格上设置单元格文本和按钮状态-dequeueReusableCellWithIdentifier:

于 2012-05-11T01:56:14.900 回答
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 == nil) 将您的代码更改为

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;
于 2012-05-11T03:44:35.940 回答