专栏首页KyXu【iOS 开发】用泛型简化 instantiateViewController

【iOS 开发】用泛型简化 instantiateViewController

使用 storyboard 的时候,我们经常会写出下面这样的代码,用来跳转到其他页面

if let editVC = self.storyboard?.instantiateViewController(withIdentifier: "EditVC") as? EditVC {
    self.navigationController?.pushViewController(editVC, animated: true)
}

最多改成这样

guard let editVC = self.storyboard?.instantiateViewController(withIdentifier: "EditVC") as? EditVC else { return }

实在是太冗长了,简化第一步,或许我们可以直接将 <code>EditVC</code> 这个类型字符串化变成 <code>"EditVC"</code>,代码变成:

guard let editVC = self.storyboard?.instantiateViewController(withIdentifier: String(describing: EditVC.self)) as? EditVC else { return }

嗯,更长了,但是既然 <code>EditVC</code> 使用了两次,这使得我们有机会把这个过程封装成一个函数,而 <code>EditVC</code> 是唯一需要传递的参数

func instantiateVC(vc:UIViewController) -> UIViewController? {
    let id = String(describing: vc.self)
    return storyboard?.instantiateViewController(withIdentifier: id)
}

// how to use
guard let editVC = instantiateVC(vc: EditVC()) as? EditVC else { return }

封装之后依然尴尬:

  1. 因为我们不能确定每次都需要函数返回 <code>EditVC</code> ,所以只能用 <code>UIViewController</code> 当做返回值,这使得我们还需要再加上 <code>as? EditVC</code> 去做类型转换,相当于还是手动使用了两次 <code>EditVC</code> ,而不是一次
  2. 传入的参数是 <code>EditVC()</code> 而不是 <code>EditVC</code> ,看起来丑陋

一次解决两个问题的答案是:泛型!

我们在函数中限定泛型 <code>T</code> 为 <code>UIViewController</code> ,但 <code>T</code> 具体是我们的 App 中的哪个子类我们不去管,通过函数的参数来指定 T 的具体类型,随后确定出我们函数的返回值为那个我们指定的 <code>T</code>

最终结果:

extension UIViewController {
    func instantiateVC<T: UIViewController>(type: T.Type) -> T? {
        let id = String(describing: T.self)
        return storyboard?.instantiateViewController(withIdentifier: id) as? T
    }
}

// how to use
guard let editVC = instantiateVC(type: EditVC.self) else { return }

前后对比:

// before
guard let editVC = storyboard?.instantiateViewController(withIdentifier: "EditVC") as? EditVC else { return }

// after
guard let editVC = instantiateVC(type: EditVC.self) else { return }

提醒: 这里我假装这个函数回避掉了直接使用字符串去传入 <code>Storyboard ID</code> 的风险,但可以这么做的前提是,这里的 <code>EditVC</code> 到 <code>"EditVC"</code> 可以直接字符串化。

如果你也要这么做的话,至少要保证你的类名的字符串化的结果和你的 <code>Storyboard ID</code> 是有固定关联的。比如 <code>EditVC</code> 对应 <code>"editvc"</code> 或 <code>"EDITVC"</code> 或 <code>"editVC"</code> (这样你只要修改字母大小写就可以了),而不是 <code>"abc123"</code> 这种随便写的东西。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 【iOS 开发】从 setNeedsLayout 说起

    本文从 <code>setNeedsLayout</code> 这个方法说起,分享与其相关的 UIKit 视图交互、使用场景等内容。

    KyXu
  • 【开源】用 UIPickerView 选择精确到街道的中国行政区划位置

    如图,做了一个四列的 <code>UIPickerView</code>,可以滑动选择精确到街道的中国行政区划信息,并返回地址,使用简单,直接像平时使用 <co...

    KyXu
  • 【iOS 开发】SnapKit 是怎样炼成的

    这是对 Swift 布局框架 SnapKit 的源码的一点分析,尝试搞清,一个好的布局框架,背后都做了些什么。

    KyXu
  • [Oauth] Oauth2.0中的授权码模式

    这种模式是我们常见的oauth形式,例如第三方登陆,qq,微博等,都是使用的授权码模式,也是很多网站系统对外提供的接口形式

    陶士涵
  • 【开源】用 UIPickerView 选择精确到街道的中国行政区划位置

    如图,做了一个四列的 <code>UIPickerView</code>,可以滑动选择精确到街道的中国行政区划信息,并返回地址,使用简单,直接像平时使用 <co...

    KyXu
  • No Code革命为什么现在爆发?

    No-code 软件貌似正在爆发:市场推广迅速,融资规模庞大,公司估值惊人(甚至出现独角兽企业),客户也心满意足。为什么是现在?为什么不是 20 年前?为什么不...

    深度学习与Python
  • Nodejs Serialport文档翻译

    本文链接 想象一个世界,你可以在那写javascript来控制搅拌机,灯,安全系统或者甚至是机器人。是的,我说的是机器人。那个世界就是这儿,现在使用node ...

    治电小白菜
  • iOS之DBL_EPSILON,FLT_EPSILON,FLT_MIN和FLT_MAX

    Dwyane
  • 2020年11月3日 星期二 工作日志 github登陆不了了,晕

    因为我之前改过很多Add按钮相关的css,怀疑是cache原因,所以清除了Chrome的cache:

    Jerry Wang
  • Swift3.1动画(一)

    Dwyane

扫码关注云+社区

领取腾讯云代金券