重用UIViewController用于模态和非模态情况

时间:2009-10-30 23:37:40

标签: iphone ios cocoa-touch uiviewcontroller uinavigationcontroller

我有一个UIViewController - 我们称之为“FormController” - 它只是一个编辑对象的表单。我想在两种不同的情况下使用它:

  1. 使用UINavigationController的presentModalViewController:方法创建新对象。

  2. 编辑现有对象 - 将视图控制器推送到UINavigationController堆栈,而不是使用对话框方法。

  3. 在模态情况下,我希望有一个带有“取消”和“完成”按钮的工具栏,但在堆栈情况下,我想只有UINavigationController提供的导航栏。

    这类似于Contacts应用程序,其中“New Contact”和“Edit Contact”屏幕似乎使用相同的视图控制器,但New Contact表单以模态方式呈现,而Edit屏幕被推送到导航堆栈

    我的问题是:在不必编写2个独立但大部分相同的视图控制器的情况下,处理这两种情况的最佳方法是什么?

    我考虑过创建一个“ModalFormController”,它通过组合封装裸“FormController”并添加一个工具栏,但我在文档中的某处读到了Apple不建议嵌套视图控制器。

6 个答案:

答案 0 :(得分:3)

为什么不使用子类?使ModalCreateFormController成为EditFormController的子类,并处理子类中特定于模式的内容。

答案 1 :(得分:2)

我所做的(有时)设置enum,指定视图控制器的类型。

例如,您可能有两种类型:Edit类型和Add(“新”)类型。

Add类型是通过模态视图控制器实现的,而Edit类型则被推送到现有的导航堆栈。

在视图控制器的-viewDidLoad:方法中,我只使用switch/case树来设置标题和其他外观特征,具体取决于上面指定的类型枚举。

关于这一点的好处是可以轻松添加新类型。缺点是处理此枚举的条件树可能会很快变得复杂,具体取决于类型的不同。

switch/case树使管理起来容易得多。

所以,这取决于你要对这两种类型做些什么。但它绝对可行。

答案 2 :(得分:2)

除了在视图控制器上有一个显式属性(正如Alex Reynolds建议的那样),我发现的另外两种方法是:

  1. 如果您正在编辑某种模型对象,请询问其当前状态。如果它已被保存,那么您处于编辑模式。否则,您处于创建模式。

  2. 查看控制器的parentViewController属性的值。如果它是UINavigationController的实例,那么您就在导航堆栈中。如果您以模态方式显示,它将是列表控制器的实例。

答案 3 :(得分:1)

Ug,我讨厌额外的伊娃......

我改用它:

if([[self.navigationController viewControllers] objectAtIndex:0] == self){

        //Modal

    }else{

        //Pushed

    }

这有点像黑客,但我们正在使用这样的逻辑:如果违规视图控制器是堆栈中的第一个,你就不能回去了。实际上我们忽略了它是否以模态显示的事实。

答案 4 :(得分:0)

我必须在我的应用程序中执行此操作并尝试了几种不同的方法,包括模态子类和&使用forwardInvocation的可重用模式助手类。我发现最好的模式是制作一个containsModalViewController方法,每个视图控制器(通常)创建并返回一个UINavigationController,供调用者使用presentModalViewController。

在大多数情况下,此方法构建并返回一个UINavigationController,其中self作为根视图控制器(重复调用方法检查self.navigationController并返回,如果它不是nil)。在其他情况下,我首先制作了一个虚拟根控制器并在第二个时间推动自我以获得后退按钮。然后可以使用一个技巧来捕捉后退按钮:http://smallduck.wordpress.com/2010/10/05/intercepting-uinavigationcontroller/

在某些情况下,视图不需要导航栏,因此此方法只调整一些标志并返回self。我甚至发现在某些情况下确实需要导航栏,使该方法调用self.view更简单,然后调整视图层次结构以添加UINavigationBar并再次返回self。但无论如何,设置通常与该方法隔离,并且调用者在每种情况下都处理它。

答案 5 :(得分:0)

Apple explains how the contacts application works under the hood:

  

要允许自定义视图控制器类用于显示和编辑内容,请覆盖setEditing:animated:方法。

您可以免费获得一些功能,例如Edit/Done按钮。