【问题标题】:Dealing with hierarchy-breaking effects in iOS games and apps处理 iOS 游戏和应用程序中的层次结构破坏效果
【发布时间】:2012-08-31 15:39:33
【问题描述】:

大约一年半前,我开始担任 iOS 开发人员,但在软件架构和组织方面遇到了一些麻烦。我使用 Apple 推荐的 Model-View-Controller 范例,而且我的代码通常是非常分层的:如果一个屏幕(例如)有一个 HUD、一个控制面板和一个显示区域,我有一个用于屏幕的主控制器和一个子控制器HUD、控制面板和显示区域的控制器。子控制器通常不知道其相邻控制器,并使用主控制器中的方法与它们进行交互。

但是,尤其是在游戏中,我经常遇到层级破坏问题,而这种模型无法优雅地解决这些问题。例如,假设我在控制面板区域中有一枚硬币,我想制作它飞向 HUD 的动画。我可以将原始硬币动画到新位置,这需要在控制面板子控制器中使用 animateCoinToPosition: 之类的方法,在主控制器中使用 getPositionForFinalCoinPositionInHUD 之类的方法;或者,我可以隐藏原始硬币并在主控制器或 HUD 控制器中创建复制硬币,这需要像 animateCoinToHUDFromStartingPosition: 这样的委托方法。我不喜欢在我的控制器中使用这种奇怪的特定方法,因为它们只是为了解决一个问题而存在,并且还暴露了层次结构。我理想的解决方案是使用一个名为 animateCoinToHUD 的方法,但这需要展平整个层次结构并将三个控制器合并为一个,这显然不值得。 (或者让子控制器访问它们的兄弟——但这基本上会产生相同的效果。然后子控制器将相互依赖,创建一个凌乱的蜘蛛网控制器而不是一个主控制器和三个大部分独立的子控制器控制器。)

而且情况往往会变得更糟。如果我想在移动硬币时显示全屏动画或粒子效果怎么办?如果我的硬币比具有许多子视图和细节的简单精灵复杂得多,以至于使用 animateCoinToHUDFromStartingPosition: 创建重复硬币效率低下怎么办?如果硬币飞到 HUD 后又返回控制面板怎么办?我是否将硬币视图“借给”主控制器,然后在动画完成时将其取回,保留原始位置/z-order/等。在临时变量中以便可以恢复它们?还有一件事:逻辑上,涉及多个子控制器的代码属于主控制器,但如果这些交互很常见,主控制器就会增长到数千行——我在许多项目中都看到过这种情况,而不仅仅是我自己的。

是否有一种一致的方法来处理这些不需要重复代码或资产、不会使我的控制器膨胀并优雅地允许我在子控制器之间共享对象的打破层次结构的效果和动作?还是我完全使用了错误的方法?

【问题讨论】:

  • 这就是我们需要白板的原因:)
  • 在过去的几天里,我已经多次阅读您的问题,但并没有真正掌握一些东西。特别是您的“根”视图控制器在这一切中扮演什么角色?听起来您也试图将其与了解层次结构隔离开来,还是我错了?
  • 否 - 根据 Apple 的指导方针,父控制器可以直接访问其所有子控制器,反之则不行。子控制器通常通过委托了解其父控制器,委托提供了父控制器必须实现的少量方法。子控制器只能通过父控制器与其兄弟控制器交互。

标签: ios architecture hierarchy paradigms


【解决方案1】:

所以,我认为您可能对“永不上升”层次结构的考虑过于字面化了。

我认为这个想法是您不知道具体父对象是什么,但是您可以定义一个协议并知道无论您的父对象是什么,它都会响应所述协议。理想情况下,您在代码中进行测试以确认它响应该协议。然后使用协议以通用方式发送消息,其中您将硬币对象传递给父对象,并让父对象将其动画化离开屏幕并进入 HUD。

然后子控制器有一个id<parent_protocol> parent; 实例变量,它们的初始化方法将其中一个作为参数。根据您的描述,您已经有了类似的东西,或者至少足以实现“子控制器通常不了解其相邻控制器并使用主控制器中的方法与它们进行交互”。

因此,从设计的角度来看,这个想法是硬币拾取发生在显示面板中,它所知道的是它的父对象有一个 pickupCoin: 方法,该方法将执行任何适当的操作捡到的硬币。显示面板不知道它进入 HUD 或其他什么,只是拾取的硬币由父控制器的 pickupCoin: 方法处理。

这里的 OOP 设计理念是将父级的所有知识都封装在协议定义中。这使得子和父更松散耦合,以便您可以交换实现该协议的任何父,并且子仍然可以正常工作。

您可以使用更松散的耦合(例如全球发布的通知),但在您描述的情况下,我认为我所概述的可能更合适且可能更高效。

这有帮助吗?

【讨论】:

    最近更新 更多