使用相同的View Controller进行添加,显示和编辑

时间:2011-04-11 02:10:59

标签: ios model-view-controller uinavigationcontroller uitableview

我正在开发一个iOS应用程序,它使用一个非常常见的基于Core Data的tableview来显示项目,当它选择一个时,它会显示更详细的视图,就像Contacts应用程序一样。详细视图本身是一个以编程方式生成的分组表,其中包含具有图片和名称的标题的自定义(nib定义)视图。表中的一些单元格是具有标签名称和文本框值的自定义单元格。在“编辑”模式下,可编辑的表格单元格(以及标题中的名称)将.clearButtonMode设置为UITextFieldViewModeAlways以显示它们是可编辑的。

我目前正在使用相同的视图控制器来显示详细信息,编辑信息,并将新记录添加到原始列表中。

当添加新项目时,视图控制器是以模态方式创建的,具有自定义init重载,该重载在视图控制器中设置一个标志以指示它正在添加记录。这允许它以编辑模式启动,如果保留编辑模式,则模型视图将被删除。右侧菜单栏按钮是通常的编辑/完成,左侧是取消按钮。当正在编辑现有项目时,左按钮(正常后退按钮)将替换为取消按钮。

我开始重新考虑是否有一个视图控制器处理三种不同的模式是要走的路。很少有问题我不知道如何处理。

1)如何通过点击“完成”来判断是否保留编辑模式?它有行动吗?如果单击取消,则操作将自行解除(添加模式)或恢复先前的值离开编辑模式。我想我可以检查我的setEditing覆盖来处理它,但似乎应该有更好的方法。

2)当进入编辑模式并且我将可编辑的文本字段设置为UITextFieldViewModeAlways时,有没有办法动画“X”按钮的外观,以便它们与常规单元格上的编辑指示器淡入?

这些问题是否有简单的解决方案,或者我的三合一视图控制器是个坏主意?对于不同的模式重新制作相同的视图似乎并不正确,但是为视图控制器设置多种模式似乎有点麻烦。

jorj

2 个答案:

答案 0 :(得分:3)

我喜欢三合一的方法并且一直使用它。有许多优点:一个xib,一个视图控制器,列表和详细视图控制器之间的一个简单协议。是的,还有一些像if (self.editing) ...这样的检查,但我比更多的视图控制器和xib更好。

为了帮助添加,我公开了委托可以设置的BOOL。

@property (nonatomic) BOOL adding;

1)内置的editButtonItem不允许你在setEditing之前拦截它:animated:当你点击完成后进行数据验证时,这是有问题的。出于这个原因,我很少使用editButtonItem并使用我自己的编辑,完成和取消按钮以及他们自己的操作方法。见下文。

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;
    }
}

答案 1 :(得分:1)

我还没有完全理解你提出的问题,但这里有一些关于结构的想法,这些想法在第一时间可能更有用......

看起来你用一个UITableViewController做得太多了,你不可避免地会遇到很多if语句和令人困惑的代码。我将其分解为两个单独的UITableViewControllers,一个用于处理主视图(以及您需要的任何后续编辑模式),然后另一个用于处理详细视图。然后,这些中的任何一个或两个都可以根据需要使用笔尖。

使用这样的两个控制器将允许您简单地将第二个detailViewController推送到导航堆栈,而不是以模态方式呈现它,这在这个实例中似乎不是显而易见的事情。

但是,如果您希望以模态方式呈现它,则可以为detailView编写协议,该协议在按下“取消”,“编辑”或“完成”按钮时发送消息。然后,第一个viewController可以实现协议并接收这些事件。

我希望有帮助...