Swift开发小技巧系列 - 更优雅的实现Segue

原文链接

正文

我们在实际开发中偶尔会遇到一些很傻很天真的BUG,结果花了很长时间调试,最后发现这些BUG大多源于一个非常小的问题。最常见的就是在一个字符串中敲错了一两个字母。在实际开发中我们又不得不面对很多读取资源文件的操作,这些操作很多都需要直接操作资源文件名称的字符串来完成。

比如初始化Image

let image = UIImage(named: "checklist_not_completed_20x20_")

注:从Xcode8开始,读取image可以使用Image Literal

Perform Segue

self.performSegue(withIdentifier: "showDetail", sender: self)

这样其实有两个问题:

  1. 对于字符串Xcode IDE没有代码提示功能,重复敲这些字符串很费时间,并且当字符串稍微复杂点时,你有一定的概率敲错,增加了出BUG的概率。
  2. Xcode IDE也不会为字符串提供编译时检测,所以如果敲错,你只能等测试出现BUG,然后去查找修复,成本很高。

今天我们就来探讨下怎么优化Segue,来解决我们上面提到的问题。

public protocol CustomSegueProtocol {
    associatedtype CustomSegueIdentifier: RawRepresentable
    func performCustomSegue(_ segue: CustomSegueIdentifier, sender: Any?)
    func customSegueIdentifier(forSegue segue: UIStoryboardSegue) -> CustomSegueIdentifier
}

首先定义一个协议CustomSegueProtocol,在协议里添加一个关联类型CustomSegueIdentifier,继承与RawRepresentable协议。同时声明两个方法performCustomSegue(_::)customSegueIdentifier(_:)

extension CustomSegueProtocol where Self: UIViewController,
    CustomSegueIdentifier.RawValue == String {
    
    public func performCustomSegue(_ segue: CustomSegueIdentifier, sender: Any?) {
        performSegue(withIdentifier: segue.rawValue, sender: sender)
    }
    
    public func customSegueIdentifier(forSegue segue: UIStoryboardSegue) -> CustomSegueIdentifier {
        guard let identifier = segue.identifier,
            let customSegueIndentifier = CustomSegueIdentifier(rawValue: identifier) else {
                fatalError("Cannot get custom segue indetifier for segue: \(segue.identifier ?? "").")
        }
        
        return customSegueIndentifier
    }
}

CustomSegueProtocol添加默认实现,并且在添加一些约束。首先我们要求CustomSegueProtocol协议只能被UIViewController及其子类使用。其次关联类型CustomSegueIdentifierRawValueString,因为我们在storyboard里面设置Segue的identifier只能是String。具体实现内容比较简单,就是调用Apple原生处理segue的方法。

下面看看具体怎么使用?

class TestCustomSegueViewController: UITableViewController, CustomSegueProtocol {
    enum CustomSegueIdentifier: String {
        case showNext
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        performCustomSegue(.showNext, sender: self)
    }
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        switch customSegueIdentifier(forSegue: segue) {
        case .showNext:
            // Configuration for next page
        }
    }
}

首先让你的UIViewController继承CustomSegueProtocol协议。然后把该协议的关联类型CustomSegueIdentifier定义为枚举类型,并列出所有的segue。然后在操作segue的时候调用performCustomSegue(_::)customSegueIdentifier(_:)这两个协议函数。

总结

  • 通过上面的改造,我们用新的方式来操作segue有以下一些好处:

    1. Xcode 的代码提示功能,减少了敲错字母引起BUG的概率
    2. 因为新的CustomSegueIdentifier是个强类型,Xcode能在编译时期对其进行类型检测。
    3. UIViewController统一用枚举类型定义所有的segue,方便管理维护,同时也可以充分利用枚举一些特性。
  • 具体详细代码请参考SwiftDevHints

联系方式

  • 微博
  • Twitter
  • GitHub
  • 博客

备注

我们在软件开发的过程中,为了提高效率,其中很重要的一环就是把反复使用到的功能或模块封装起来。因此我在GitHub上开源了一个小工具集 - SwiftDevHints,来总结自己在实际项目开发过程中封装的一些小功能。

刚刚介绍的只是其中一个小功能,想看看其它更多功能,请直接点击SwiftDevHints。如果您觉得对您有所帮助,请给一个star吧。

你可能感兴趣的:(Swift开发小技巧系列 - 更优雅的实现Segue)