Swift 3:如何在没有多个if let语句的情况下为不同选项类型的变量赋值?

Swift 3: How to assign variable of different option types without multiple if let statements?

首先,如果标题含糊不清,我深表歉意。请随意更改它以符合问题描述。

我会尽力描述我的问题,但首先是一段代码:

if let vc = currentVC as? FirstViewController
{
    vc.doSameMethod()
}
else if let vc = currentVC as? SecondViewController
{
    vc.doSameMethod()
}
else if let vc = currentVC as? ThirdViewController
{
    vc.doSameMethod()   
}

基本上,我使用 if let 语句来检查可选的 nil,然后解包并分配它。

我在所有 3 个 ViewController 中都有 doSameMethod() 函数,它们使用相同的函数名称执行几乎相同的任务。

我的问题是,我怎样才能避免重复代码:

if let vc = (currentVC as? FirstViewController || current as? SecondViewController || currentVC as? ThirdViewController)
{
    vc.doSameMethod()
}

显然,上面的代码无法编译,但我想知道是否有更简单、更清晰的方法来通过检查多种类型来解包可选?

谢谢!

你可以用一个协议来做。用所有 3 个视图控制器之间的通用方法定义一个协议并使它们符合它:

protocol MyViewControllerProtocol {
    func doSameMethod()
}

class FirstViewController: UIController, MyViewControllerProtocol {
    // your code
}

class SecondViewController: UIController, MyViewControllerProtocol {
    // your code
}

class ThirdViewController: UIController, MyViewControllerProtocol {
    // your code
}

用法:

if let vc = currentVC as? MyViewControllerProtocol {
    vc.doSameMethod()
}

如果您有多个视图控制器,它们都实现了相同的方法,那么协议是一个不错的选择,如@CodeDifferent 的回答中所述。

如果每个视图控制器都有不同的界面,并且您需要根据传递给您的视图控制器做不同的事情,您可以使用带有 case let newConstant as <type>: [=18= 的 switch 语句的变体]

这是在 prepareForSegue 方法中使用的示例代码片段,您可能在其中处理到视图控制器的几个不同 classes 之一的 segue:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
  switch segue.destinationViewController {
    case let fooViewController as FooViewController:
      fooViewController.delegate = self

    case let barViewController as BarViewController:
      barViewController.data = data

    default:
      break
  }
}

在您的情况下,它会显示为

switch currentVC {
  case let firstVC as FirstViewController:
      //code for FirstViewController
  case let secondVC as SecondViewController:
      //code for SecondViewController
  case let thirdVC as ThirdViewController:
      //code for ThirdViewController
}

如果 currentVC 是指定的 class 的对象,则选择一个案例。此外,在该 case 语句中,有一个定义为正确类型的局部常量,就像在 if let 中一样。


编辑 - 从 "Matching based on class - great for prepareForSegue" 复制的完整示例,来自现已失效的 Whosebug 文档:

你也可以根据你打开的东西的 class 做一个 switch 语句切换。

prepareForSegue 中的一个有用示例。我曾经根据 segue 标识符进行切换,但这很脆弱。如果您稍后更改故事板并重命名 segue 标识符,它会破坏您的代码。或者,如果您对同一视图控制器 class(但故事板场景不同)的多个实例使用 segue,则无法使用 segue 标识符来确定目标的 class。

Swift switch 语句来拯救。

使用Swift case let var as Class语法,像这样:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
  switch segue.destinationViewController {
    case let fooViewController as FooViewController:
      fooViewController.delegate = self

    case let barViewController as BarViewController:
      barViewController.data = data

    default:
      break
  }
}

在 Swift 3 中语法略有变化:

override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?) {       
  switch segue.destinationViewController {
    case let fooViewController as FooViewController:
      fooViewController.delegate = self

    case let barViewController as BarViewController:
      barViewController.data = data

    default:
      break
  }
}