如何使用自定义 tableviewcells 正确添加和删除对象到 tableview?

Posted

技术标签:

【中文标题】如何使用自定义 tableviewcells 正确添加和删除对象到 tableview?【英文标题】:How to properly add and delete objects to tableview with custom tableviewcells? 【发布时间】:2011-12-15 10:05:12 【问题描述】:

我目前正在开发一个行为类似于 Messages.app 的应用。 MasterViewController 是主视图,它在其中加载联系人姓名、时间和最新消息的 sn-p 表。当您点击一个特定的单元格时,它会滑到 DetailViewController 中,它会在其中加载我发送给联系人的消息以及最新的完整消息。点击后退按钮返回到 MasterViewController。点击 rightBarButtonItem 会打开一个 ComposeViewController(模式),用户可以在其中向特定联系人撰写消息。这个应用程序与默认 Messages.app 的不同之处在于它在发送消息之前有一个延迟计时器。 ComposeViewController 有一个用于输入消息的文本字段、一个用于选择联系人的按钮、一个用于选择时间延迟的按钮、一个用于发送的按钮、一个用于取消计时器的按钮以及一个用于关闭 ModalViewController 的按钮。

我完全删除了发送实际 SMS 消息的功能。我只是向用户展示了一个警报视图,告诉他/她消息已发送,以及他/她是否想要撰写新消息。点击取消将关闭 ModalViewController 并返回到 MasterViewController。

问题是,我不能让行出现在表格上,也不能在表格中添加和删除单元格。

这是我的 MasterViewController 的 viewDidLoad 中的一些代码:

[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

// Delete button to delete messages
UIBarButtonItem *deleteBarButtonItem = [[UIBarButtonItem alloc] 
                                      initWithBarButtonSystemItem:UIBarButtonSystemItemTrash
                                      target:self 
                                      action:@selector(deleteText)];
self.navigationItem.leftBarButtonItem = deleteBarButtonItem;


// Compose button to go to compose messages
UIBarButtonItem *composeBarButtonItem = [[UIBarButtonItem alloc] 
                                         initWithBarButtonSystemItem:UIBarButtonSystemItemCompose
                                         target:self 
                                         action:@selector(composeText)];
self.navigationItem.rightBarButtonItem = composeBarButtonItem;

[deleteBarButtonItem release];
[composeBarButtonItem release];

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *message = [defaults objectForKey:kMessageText];
NSString *contactname = [defaults objectForKey:kContactNameText];
NSString *timestamp = [defaults objectForKey:kTimeStampText];

[messageDetails initWithObjectsAndKeys:contactname, kContactNameKey, message, kContactMsgKey, timestamp, kContactTimeKey, nil];

NSMutableArray *messageInfo = [[NSMutableArray alloc] initWithObjects:messageDetails, nil];

self.messagesList = messageInfo;

[messageInfo release];

[super viewDidLoad];

这是 cellForRowAtIndexPath 中的代码:

CustomCellViewController *customCell = (CustomCellViewController *)[tableView dequeueReusableCellWithIdentifier:@"CustomCellViewController"];

if (customCell == nil)

    NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"CustomCellViewController"
                                                 owner:self 
                                               options:nil];
    for (id oneObject in nib) if ([oneObject isKindOfClass:[CustomCellViewController class]])
        customCell = (CustomCellViewController *)oneObject;


NSUInteger row = [indexPath row];
NSDictionary *messages = [self.messagesList objectAtIndex:row];

customCell.nameLabel.text = [messages objectForKey:kContactNameKey];
customCell.nameLabel.textColor = [UIColor whiteColor];
customCell.messageLabel.text = [messages objectForKey:kContactMsgKey];
customCell.messageLabel.textColor = [UIColor lightGrayColor];
customCell.timeLabel.text = [messages objectForKey:kContactTimeKey];
customCell.timeLabel.textColor = [UIColor blueColor];

customCell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

return customCell;

删除单元格的代码如下:

- (void)tableView:(UITableView *)tableView commitEditingStyle(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath

    if (editingStyle == UITableViewCellEditingStyleDelete)
    
    // Delete the row from the data source.        
    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]withRowAnimation:UITableViewRowAnimationFade];

    [messagesList removeObjectAtIndex:indexPath.row];
    [self.tableView reloadData];
    
    else if (editingStyle == UITableViewCellEditingStyleInsert) 
    // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
       

【问题讨论】:

最后一段代码在哪里?这将创建您的主视图控制器的一个新实例,它不会作用于您当前的主表。 它位于模态视图控制器的实现中,您将文本放入文本字​​段并点击按钮以关闭模态视图控制器。 【参考方案1】:

您在其中创建主视图控制器的新实例的最终代码 sn-p 是问题所在。

这不是您要查找的视图控制器。由于您已经以模态方式呈现了详细视图控制器,因此您可以通过详细控制器的parentViewController 属性访问主控制器:

MasterViewController *master = (MasterViewController*)self.parentViewController;

通常在这种情况下使用的其他设计模式:

在主控制器中创建新对象并在表中插入行,然后将新对象传递给详细控制器进行更新 为细节控制器创建一个委托协议,您的主控制器符合该协议。推送时将详细控制器委托给主控制器

后者几乎是您为所有实际目的所做的事情,除了您的详细控制器对主控制器的了解比它需要的更多(即您正在导入整个主 .h 文件,而不仅仅是知道它符合协议)。

关于您的数据结构,我不明白您希望在这里有多行 - 您将一条消息存储在用户默认值中,然后使用该消息创建一个数组。我知道您最终不打算使用默认值来存储它,但我希望看到一个字典数组存储在一个键下的默认值中,然后每个字典代表表中的一行,以及各种详细信息根据您的消息、联系人姓名键等存储为字典中的字符串。

您必须创建从默认值返回的数组的可变版本,因为它总是返回一个不可变数组。

在您的 cellForRow... 方法中,您将从数组中获取适当的字典并从中填充单元格。

添加新行时,您将创建一个新字典以传递给您的详细信息控制器。

删除一行时,您将从数组中删除相关字典。

【讨论】:

非常感谢 jrturton!我会试试你的建议。 知道了。我在编辑代码时意识到了一些事情。添加单元格时,我必须为详细视图控制器和主视图控制器创建一个可变数组和一个可变字典。数据将来自模态视图控制器内的文本字段。我已经更新了我的代码。如果您有时间,可以在这里查看:dl.dropbox.com/u/7539490/texText.zip。没有错误,但值没有出现在表格中。 :( 我现在在移动,所以我无法访问该文件。查看上面的其余代码,您每次在 cellForRowAtIndexPath 中创建一个新数组并将其分配给您的表视图数据源数组似乎并不正确。你能用你的数据结构更新问题吗?数组、字典等应该是什么? 当然。我将使用链接中的代码和问题更新代码和问题。感谢您的帮助 jrturton。 谢谢。这其实也是我的目标。将值保存到 Core Data 而不是仅保存在 NSUserDefaults 上。我不明白为什么我的 MutableDictionary 和 MutableArray 在我的代码中显示为空(与上面的代码相同):dl.dropbox.com/u/7539490/texText.zip。再次感谢 jrturton。我会尝试更多地检查我的代码。也许,我需要为值创建一个委托才能正确传递。

以上是关于如何使用自定义 tableviewcells 正确添加和删除对象到 tableview?的主要内容,如果未能解决你的问题,请参考以下文章

在情节提要中使用自定义 tableviewcells 时,IBOutlet 为零

如何在 3.0 之后使用 initWithStyle 制作自定义 TableViewCell

如何使用标签或标识符将多张图片添加到自定义 tableviewcells

iOS 7 中自定义 TableViewCell 中的自动布局问题

自定义 TableViewCell 中忽略自动布局

自定义 tableviewcell 和自动布局