使用相同的 View Controller 进行添加、显示和编辑
Posted
技术标签:
【中文标题】使用相同的 View Controller 进行添加、显示和编辑【英文标题】:Using the same View Controller for add, display, and edit 【发布时间】:2011-08-02 17:39:33 【问题描述】:我正在开发一个 ios 应用程序,它使用一个非常常见的基于核心数据的表格视图来显示项目,当它选择一个时,它会显示一个更详细的视图,就像联系人应用程序一样。详细视图本身是一个以编程方式生成的分组表,带有一个自定义(笔尖定义)视图,用于具有图片和名称的标题。表格中的一些单元格是具有标签名称和文本框值的自定义单元格。在“编辑”模式下,可编辑的表格单元格(以及标题中的名称)将 .clearButtonMode 设置为 UITextFieldViewModeAlways 以显示它们是可编辑的。
我目前正在使用同一个视图控制器来显示详细信息,编辑信息,并在原始列表中添加新记录。
当添加新项目时,视图控制器会以模态方式创建,并带有自定义初始化重载,该重载会在视图控制器中设置一个标志以指示它正在添加记录。这允许它以编辑模式启动,如果离开编辑模式,模型视图将被丢弃。右侧菜单栏按钮是通常的编辑/完成,左侧是取消按钮。编辑现有项目时,左侧按钮(正常的后退按钮)将替换为取消按钮。
我开始重新考虑是否让一个视图控制器处理三种不同的模式是要走的路。有几个问题我不知道如何处理。
1) 如何通过点击“完成”来判断是否退出了编辑模式?有行动吗?如果点击取消,则操作将自行关闭(添加模式)或恢复先前的值离开编辑模式。我想我可以检查我的 setEditing 覆盖来处理它,但似乎应该有更好的方法。
2) 当进入编辑模式并且我将可编辑的文本字段设置为 UITextFieldViewModeAlways 时,有没有办法为“X”按钮的外观设置动画,以便它们与常规单元格上的编辑指示器一起淡入?
这些问题是否有简单的解决方案,或者我的三合一视图控制器是个坏主意?为不同的模式重新制作同一个视图似乎不太合适,但是为一个视图控制器设置多个模式似乎有点麻烦。
jorj
【问题讨论】:
【参考方案1】:我喜欢三合一的方法并一直使用它。有很多优点:一个 xib,一个视图控制器,列表和详细视图控制器之间的一个简单协议。是的,还有更多检查,例如if (self.editing) ...
,但我比更多的视图控制器和 xib 更喜欢它。
为了帮助添加,我公开了一个代表可以设置的 BOOL。
@property (nonatomic) BOOL adding;
1) 内置的editButtonItem 不允许你在setEditing:animated 之前拦截它:当你在点击Done 之后进行数据验证时,这是有问题的。出于这个原因,我很少使用 editButtonItem 并使用我自己的 Edit、Done 和 Cancel 按钮以及它们自己的操作方法。见下文。
2) 为此,我喜欢 UITableView 的 reloadSections:withRowAnimation。它可能适用于您的情况。
- (void)edit:(id)sender
self.editing = YES;
- (void)done:(id)sender
// data validation here
if (everythingChecksOut)
//save here
else
return; //something didn't validate
//if control reaches here all is good
//let the delegate know what happened...
if (self.adding)
[self.delegate didFinishAddingWithData:self.yourData];
else
[self.delegate didFinishEditingWithData:self.yourData];
self.adding = NO;
self.editing = NO;
- (void)cancel:(id)sender
[self.view endEditing:YES]; //in theory, forces the view that is editing to resign first responder
//in practise I find it doesn't work with the YES parameter and I have to use my own flag
// roll back any changes here
self.editing = NO;
if (self.adding) //let the delegate know we cancelled the add...
[self.delegate didCancelAdd];
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
[super setEditing:editing animated:animated];
//set your nav bar title
[self.tableview.editing = editing]; //you may or may not require this
[self.tableview reloadSections... withRowAnimation:yourChoice];
if (editing)
//install your Done and Cancel buttons
else
//remove Cancel and put the Edit button back
然后在 viewDidLoad...
- (void)viewDidLoad
[super viewDidLoad];
//whatever else you do
if (self.adding)
self.editing = YES;
【讨论】:
【参考方案2】:我还没有完全理解你提出的问题,但这里有一些关于结构的想法,它们可能在第一个实例中更有用......
看起来你用一个 UITableViewController 做的太多了,不可避免地你会得到很多 if 语句和混乱的代码。我会将其分解为两个单独的 UITableViewController,一个用于处理主视图(以及您需要的任何后续编辑模式),另一个用于处理详细视图。然后,这些中的一个或两个都可以根据需要使用笔尖。
使用像这样的两个控制器将允许您简单地将第二个 detailViewController 推送到导航堆栈上,而不是模态地呈现它,这在这种情况下似乎不是显而易见的事情。
但是,如果您希望它以模态方式呈现,您可以为 detailView 编写一个协议,该协议在按下“取消”、“编辑”或“完成”按钮时发送消息。然后第一个 viewController 可以实现协议并接收这些事件。
希望对你有帮助……
【讨论】:
以上是关于使用相同的 View Controller 进行添加、显示和编辑的主要内容,如果未能解决你的问题,请参考以下文章
在 Modal View Controller 中使用 UINavigationController 进行内存管理
Asp.net mvc基础Controller给View传递数据的方式