Swift 面向协议 - 为类提供基于 Storyboard 的初始化方法

之前我们说过了运用面向协议的思想为控件添加 action 今天我们再来写一个基于 Storyboard 的初始化方法。在我的项目中,我没有将所有的 controller 都放在一个 Storyboard 文件中,原因有两个:

  • Controller 很多的时候不方便查找对应的 Storyboard
  • 打开 Storyboard 会非常卡。

所以我将 Controller 拆分成一个个的 Storyboard 文件。在对应的类中,我需要在每个类都写上一个初始化方法:

1
2
3
4
static func instantiate() -> HomeViewController {
return UIStoryboard(name: .home)
.instantiateViewControllerWithClass(type: HomeViewController.self)
}

当你的 App 页面非常多的时候你会发现到处都是 instantiate() 方法,所以我们需要用 Swift 中强大的 Protocol 思想进行一次优化了。

首先我们需要声明一个协议 StoryboardLoadable

1
2
protocol StoryboardLoadable where Self: UIViewController {
}

在协议中我们可以什么都不用写。接下来我们扩展这个协议:

1
2
3
4
5
6
7
extension StoryboardLoadable {
static func instantiate() -> Self {
/// 移除类的 viewcontroller 后缀,创建 storyboard 名
let sbName = "\(self)".removingSuffix("ViewController")
return UIStoryboard(name: sbName).instantiateViewControllerWithClass(type: Self.self)
}
}

举个例子,我的登录页面的控制器名称为 LoginViewController,对应的 Storyboard 名称为 Login,所以我需要执行 let sbName = "\(self)".removingSuffix("ViewController") 来生成 Storyboard 名称。

然后我们在我们的类中遵循这个协议即可。

1
2
class LoginViewController: StoryboardLoadable {
}

以后就可以在其他地方这样初始化你的类了:

1
let loginVC = LoginViewController.instantiate()