performSegueWithIdentifier 或 presentViewController 是更好的做法

Is it better practice to performSegueWithIdentifier or presentViewController

如果我使用的是情节提要,创建转场并使用 performSegueWithIdentifier 或仅使用 presentViewController 将用户从一个视图控制器移动到下一个视图控制器是更好的做法。

对于这个例子,假设我们使用 Swift 5 并且我有 2 个视图控制器:MainViewController 上的联系人 TableView 和 DetailViewController 上该联系人的详细信息。

在我的代码中,我使用了 presentViewController,但由于我是 iOS 开发的新手,我不确定这是否是最好的方法。

他们都做同样的事情,但我通常使用 Present 所以当我想改变行为时,例如,让按钮打开另一个 VC,我只是改变标识符,我不必须删除 segue 并创建一个新的。 还有很多 segues 会让你的故事板看起来像意大利面条

为了便于说明,我们假设情节提要中的情况如下:

ViewController1
    |----> modal segue "toVC2" emanating from ViewController1
        |----> ViewController2, identifier "VC2"

然后在 ViewController1 代码中,这两件事之间绝对没有功能上或有效上的区别:

  • 使用标识符"toVC2"调用performSegue
  • 在故事板上用标识符 "VC2" 调用 instantiateViewController 并调用 present

话虽如此,我将为每种方式 "better" 提供一个案例。

为什么 segue 可能会更好

我的示例中的 segue 看起来并没有好多少,因为我们仍然必须使用代码来调用 performSegue。但是,假设 segue 不是来自视图控制器,而是来自视图控制器视图中的 button。这是一个 action segue,现在当用户点击我们的按钮时,segue 将自动执行,无代码 需要执行它。您甚至不需要知道标识符。 (字符串标识符是犯错误的好方法。)

为什么 instantiatepresent 可能更好

转场有一些非常可怕的地方,无论是动作转场还是使用 performSegue 手动触发的转场 — 也就是说,当(经常发生)您想将数据从第一个视图控制器传递到第二。如果使用 segue,则必须在 prepare(for:sender:) 的实现中执行 data-passing。这非常混乱,因为您必须检查 segue 标识符并将目标转换为正确的 class。此外,如果有多个 segue,prepare 将成为一个混乱的瓶颈。如果我们还调用了 performSegue,我们将在两个不同的地方进行操作——我们调用 performSegue 的方法,以及 prepare.

的单独实现

相比之下,如果我们调用instantiateViewController,返回给我们的是视图控制器实例本身。我们仍然需要转换,但现在我们可以立即传递数据,没有 prepare 的 "waiting",也没有通过瓶颈。因此,这是一种更加清晰和封装的处理方式。

此外,这似乎很明显,但是说 present 的一个好处是它告诉我们代码中的转换 是什么 。如果你只是使用一个 segue 标识符,那么这是一个模态 segue 的事实在故事板中被隐藏了。

我更喜欢哪个?

都没有。如果可以的话,我宁愿完全不为呈现的视图控制器使用故事板。我使用视图控制器和同名笔尖。这样,我只需实例化视图控制器本身并将数据和 present 传递给它,无需强制转换,也不需要任何标识符。

所以我是说故事板一点都不好吗?

没有。故事板具有绘制应用程序场景结构的优点,尤其是当您确实使用转场时。但是,如果您 打算对视图控制器使用 segue,那么我真的不明白首先将该视图控制器保留在情节提要中的意义。同名笔尖机制更清晰、更简洁。而且,我认为 prepare(for:sender:) 机制是整个故事板架构中的一个 near-fatal 缺陷; Stack Overflow 上显示的绝大多数错误都是此缺陷的结果。

[EDIT 请注意,我对 segues 的许多反对意见将在 iOS 13 中消失,其中源视图控制器将能够使用代码来调用目标视图控制器的初始化程序。]