iOS重构之面向协议编程实践

栏目: IOS · 发布时间: 6年前

内容简介:最近一段时间都在进行iOS客户端的重构,参考了许多iOS重构方面的资料,在重构的过程中也遇到一些困难,同时总结了不少经验,在这里和大家分享一下。这将会是一个系列的文章,每一篇文章都会从一个具体的、普遍性的问题出发,然后分析和解决这个问题。插一句,软件开发本身是一件工程化的事情,虽然有一些理论上的指导和支持,但终归还是要从实际项目中出发,找到适合项目本身的最优解。我在这里提到的一些实践不一定适合每一个项目,甚至在某些情况下不适用,所以欢迎大家多多讨论交流,我们的终极目标都是写出具有可读性、可维护性、可拓展性

最近一段时间都在进行iOS客户端的重构,参考了许多iOS重构方面的资料,在重构的过程中也遇到一些困难,同时总结了不少经验,在这里和大家分享一下。这将会是一个系列的文章,每一篇文章都会从一个具体的、普遍性的问题出发,然后分析和解决这个问题。

插一句,软件开发本身是一件工程化的事情,虽然有一些理论上的指导和支持,但终归还是要从实际项目中出发,找到适合项目本身的最优解。我在这里提到的一些实践不一定适合每一个项目,甚至在某些情况下不适用,所以欢迎大家多多讨论交流,我们的终极目标都是写出具有可读性、可维护性、可拓展性的高质量代码。

问题:如何管理界面跳转的代码 回想一下你的项目中,大部分界面跳转的代码是写在哪里的?最简单方便的,直接写在ViewController中。这种方式很好理解,因为ViewController原生就提供了界面跳转的方法prsentVC/pushToVC。 随着项目逐渐复杂,你可能会发现,有一些VC可以从很多不同的VC跳转而来,如果按照原来的方式,就会有很多界面跳转代码的重复。于是我们可能会创建一个XXRouter的类,把跳转到XXViewController的代码提取出来,放到XXRouter中管理。

class XXRouter {
  var newVC:XXViewController {
    // 或者从Storyboard/Xib创建
    return XXViewController()
  }
  func presentXXVC(_ fromVC:UIViewController){
    let xxVC = newVC
    //XXViewController初始化
    vc.present(xxVC)
  }
}
复制代码

于是,在其他需要跳转到XXViewController的VC中,只需要新建一个XXRouter,调用router.presentXXVC()就可以实现界面跳转,也做到了统一管理。

class MyViewController:UIViewController {
  fileprivate var router = XXRouter()
  func someFunc() {
    // do something 
    router.presentXXVC()
  }
}
复制代码

这种方式已经能满足我们大部分的要求了,只不过每次都需要创建一个Router实例,当然也可以使用单例。 其实我们可以借助Swift的协议扩展Protocol Extension,可以把Router的实现变得更加直观和优雅

协议扩展Router模式 Swift相比其他OOP语言的一个比较大的特点就是面向协议Protocol Oriented,理论知识这里就不在赘述了,给一个苹果的官方文档的链接Protocol-Oriented Programming in Swift 下面就是我们的实践,这次我们使用protocol来处理我们的界面跳转的代码

protocol XXRouter {}
extension XXRouter {
  var newVC:XXViewController {
    // 或者从Storyboard/Xib创建
    return XXViewController()
  }
  func presentXXVC(_ fromVC:UIViewController){
    let xxVC = newVC
    //XXViewController初始化
    vc.present(xxVC)
  }
}
复制代码

看起来和之前的实现几乎一模一样,但是在VC中我们就不需要创建XXRouter的实例,而是直接让ViewController实现我们的XXRouter

extension MyViewController:XXRouter{}
class MyViewController:UIViewController {
  func someFunc() {
    // do something 
    self.presentXXVC(self)
  }
}
复制代码

这种方式还有一个好处就是可以很直观的看到界面间的跳转关系,尤其是一个界面可以跳转到不同界面的情况,比如

extension MyViewController:XXRouter,YYRouter,ZZRouter{}
class MyViewController:UIViewController{}
复制代码

上面的代码几乎达到了代码即文档:MyViewController这个界面,可以跳转到XX、YY和ZZ三个ViewController。 更进一步,借助extension的where条件扩展,我们还可以省略掉fromVC呢!

protocol XXRouter {}
extension XXRouter where Self:UIViewController {
  var newVC:XXViewController {
    // 或者从Storyboard/Xib创建
    return XXViewController()
  }
  
  func presentXXVC(){
    let xxVC = newVC
    // XXViewController初始化
    // 直接使用self,因为where指定当前扩展的是UIViewController
    self.present(xxVC)
  }
}
复制代码

这种方式修改的成本很小,只是提取和挪动界面间跳转代码,几乎不会出现什么错误,用非常小的成本很大程度提高了项目代码的可读性和可维护性。目前我们项目中的界面跳转就是用这种方式进行了重构。

其他的跳转方案 最后,再简单分析一下其他两种界面跳转的解决方案

Storyboardsegue 跳转 这种方式对于 Storyboard内ViewController 之间的简单跳转来说十分方便,不用写一行代码。而且.storyboard文件中把一个个分离的 ViewController 通过图的方式有机地连接在一起,清晰得展现出了项目内 ViewController 跳转的路径。

不足:涉及到页面之间传值或者需要做额外初始化工作的ViewController,需要在代码中实现delegate,和直接代码跳转相比没有太大差别。

对于需要额外初始化的 ViewController ,把一个跳转流程分离到两个地方实现,个人觉得更加不利于维护。 模仿前端的URL Router跳转,比如MGJRouter 这种方式受Web URL跳转方式的启发,通过注册页面为URL Scheme的方式进行跳转,比较适合Hybird应用,给跳转网页和跳转ViewController一个统一的入口,便于维护

不足:额外多了注册ViewController或实现Router Protocol的操作。 侵入性大,需要在项目初期就使用这种方式,不利于重构。 这篇文章就写到这里啦,iOS重构的文章还有挖了几个坑,近期会填完!如果各位觉得本文对你有帮助的话,请点一个喜欢,谢谢~


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

React 进阶之路

React 进阶之路

徐超 / 清华大学出版社 / 2018-4 / 69.00元

《React进阶之路》详细介绍了React技术栈涉及的主要技术。本书分为基础篇、进阶篇和实战篇三部分。基础篇主要介绍React的基本用法,包括React 16的新特性;进阶篇深入讲解组件state、虚拟DOM、高阶组件等React中的重要概念,同时对初学者容易困惑的知识点做了介绍;实战篇介绍React Router、Redux和MobX 3个React技术栈的重要成员,并通过实战项目讲解这些技术如......一起来看看 《React 进阶之路》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具