在不知道当前视图状态的情况下实现openURL

时间:2012-12-31 00:03:24

标签: ios cocoa-touch uiviewcontroller url-scheme appdelegate

我正在实现一个自定义URL方案,它将实体添加到我的数据模型中。实体的详细信息包含在URL中。基本的想法是,电子邮件链接(或来自其他应用程序的链接)将打开我的应用程序并添加新实体。

问题是,我无法确定我的应用在响应时会处于哪种状态。可能会有任意数量的视图控制器。如果实体列表在视图中,我需要为该实体插入一个新行。如果屏幕上显示其他视图,我需要做出不同的反应。有些观点也可能是模态的。

当发生这种情况时,我会对一个简单的模式感到满意 - 中止用户当前正在做的任何事情,然后弹出到根视图控制器。从这里开始,我可能会推送到一个控制器,在那里我将展示要添加的新实体。

我尝试总是忽略任何显示的模态并弹出到根目录,其好处是不需要知道究竟是什么显示:

[(UINavigationController *)self.window.rootViewController dismissViewControllerAnimated:NO completion:nil];
[(UINavigationController *)self.window.rootViewController popToRootViewControllerAnimated:NO];

这种方法运作得相当好,但至少有两种情况不足:

  1. 如果在呈现模态时创建了某个对象(然后使用模态修改新对象),并且如果用户取消则委托有责任删除该对象,该实体将保持活动状态
  2. 如果正在显示UIActionSheet,则所有投注均已关闭。我不能在不知道显示它的控制器,有权访问该控制器,并向其发送消息以解除操作表的情况下解雇这一点。如果不这样做,则会弹出根视图控制器,但操作表将保留在屏幕上。操作表上的后续点击当然会导致崩溃,因为显示它的控制器已经消失。
  3. 我怎么能强有力地处理这个问题?我是否应该尝试专门找出当前呈现的视图控制器,并依次处理每个场景?或者是否有一个更具可扩展性的解决方案,每次添加控制器或更改我的应用程序流程时都不需要更新?

1 个答案:

答案 0 :(得分:3)

听起来你正在尝试做几件事:

  1. 当用户点击您的自定义网址时,您希望在模型中添加“实体”。
  2. 您希望以某种EntityListViewController显示此新实体,这可能是也可能不在ViewController堆栈上。
  3. 您(可能)想要弹出EntityListViewController上方的所有视图控制器。
  4. 您希望用户知道添加了新实体(可能只是通过执行第2项)。
  5. 您想要推送某种EntityViewController,或者如果视图控制器堆栈中当前有EntityViewController,您希望使用新实体的数据重新加载。
  6. 听起来你已经准备好了第1项了,因为你没有明确地询问有关处理url点击和插入新模型对象的信息。

    对于其他人来说,灵活的MVC-ish模式将是使用NSNotificationCenter。

    插入新模型对象的代码将“发布”通知:

    [[NSNotifcationCenter defaultCenter] postNotificationName:@"entity_added" object:myNewEntity];
    

    然后你的各种UI元素(例如,UIAlertView和UIViewController子类)将监听此通知并采取一些有用的操作(如关闭自己,或者在EntityListViewControllerEntityViewController的情况下,重新加载自己)。

    例如,UIViewController子类可能会这样做:

    -(void) viewDidLoad
    {
      [super viewDidLoad];
      [[NSNoticationCenter defaultCenter] addObserver:self selector:@selector(onNewEntity:) name:@"entity_added" object:nil];
    
    
    -(void) onNewEntity:(MyEntity*)entity
    {
       // close, or redraw or...
    }
    
    -(void) dealloc
    {
      [[NSNoticationCenter defaultCenter] removeObserver:self];
      // if not using ARC, also call [super dealloc];
    }
    

    为了让您的生活变得简单(并且不要过多担心所有不同的UI状态),我会考虑在通知发生时执行此操作:

    1. EntityListViewController重绘自己(如果有什么东西在它上面并不重要)。
    2. 在导航栏中显示某种短暂的指示符(或您知道的其他地方始终可见),或播放声音,以便用户知道已添加实体。
    3. 就是这样。
    4. 如果采用这种方法,那么对用户正在/正在做的事情的影响微乎其微,但当他们导航回EntityListViewController时,它已经显示了所有新实体。

      显然,如果单击自定义URL可能会删除现有实体,那么弹出与该实体相关的任何视图控制器会更为重要。但这也是你可以使用相同的模式做的事情 - 让模型或控制器发布通知,然后让各种UI元素听取它并采取适当的行动。