首页 > 解决方案 > performSegueWithIdentifier 或 presentViewController 是更好的做法吗

问题描述

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

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

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

标签: iosswiftstoryboardsegue

解决方案


为了便于说明,我们假设故事板中的情况如下:

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

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

  • performSegue使用标识符调用"toVC2"
  • 使用标识符调用instantiateViewController情节提要"VC2"并调用present

话虽如此,我会为每一种方式都比另一种方式“更好”提出一个理由。

为什么segue可能会更好

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

为什么instantiate并且present可能会更好

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

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

此外,这似乎很明显,但要说的好处present是,这在代码中就告诉我们过渡什么。如果您只使用一个转场标识符,那么这是一个模态转场这一事实将隐藏在情节提要中。

我更喜欢哪个?

两者都不。如果我能提供帮助,我宁愿完全不使用故事板来呈现视图控制器。我使用视图控制器和同名笔尖。这样,我只需实例化视图控制器本身并将数据和present它传递给它,不需要强制转换,也不需要任何标识符。

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

不,Storyboards 具有绘制应用程序场景结构的优点,尤其是在您使用 segues 的情况下。但是,如果您打算对视图控制器使用 segue,那么我并没有真正看到首先将该视图控制器保留在情节提要中的意义。同名笔尖机制更清晰,更干净。此外,我认为该prepare(for:sender:)机制是整个故事板架构中近乎致命的缺陷。Stack Overflow 上显示的绝大多数错误都是此缺陷造成的。

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


推荐阅读