YongSir

专业程序员伪装者

swift-tip之开发中的封装讨论

swift 开发经验之常见封装讨论

公司的项目终于全面swift化了,转到swift之后最大的感受在于写代码的自由性,不管是struct和enum都被大大拓展,个人感受来说确实码砖时开心了很多,代码也简洁了很多,即便是自己初级的水平,但还是想斗胆来做一下常用功能需求在swift中的实现及封装的讨论,比如对网络部分的封装,权限请求的封装等等,鉴于水平有限,诸多不足,贻笑大方,且作消遣排挤之用!

网络部分

作为正常的地球人+小公司独立开发属性,使用Matt大神的Alamofire我想是的选择,当然如果您司有自己的私有库,那就不存在这个问题的讨论了,所以也很自然的选择了它。

作为最著名的第三发框架和诸多开发者信誉加成,Alamofire本身已足够优秀,但在使用中,往往我们都会按照自己的习惯做一下封装,这也是这一部分的主题,笔者会介绍一下自己的习惯:

总体原则:

  1. 去耦: 不管怎样优秀,但Alamofire终归是第三方框架,前司升级AFNetwork 3.0的症痛还历历在目,如果刨除当时自己半路接手+经验不足的安慰理由外,对这种高耦合式的使用第三方框架的教训不够也是主要原因,吃过亏自然就知道了,所以原则上,在使用任何第三方框架时,尽量自己做一曾封装,即便是意义不大技术含量低级的封装,对第三方 API 的调用尽量集中在封装内,这也就是为何我一直推崇繁复的 CoreData 而避免所谓便利的 Rleam 等的原因。

  2. 简化: 跟后台紧密配合,单独剥离不同url请求,做到每一个请求就是对应一个方法,这样最大的好处就是请求清晰简明,别人在接手也容易

  3. 完备: 集中处理诸如权限,错误,提示的处理,集中设置请求头的属性,方法,输出请求调试内容,做到出了问题迅速定位,用户体验不割裂

以上都是常见的调调,不看也罢,主要是充分利用swift的特点,完成封装的具体过程

-------------------
🙈🙈🙈🙈🙈🙈🙈🙈 假装看不见的分割线 🙈🙈🙈🙈🙈🙈🙈🙈🙈
-------------------

避免直接使用String作为参数,借助swift的enumstruct避免 面向字符串编程

如使用枚举集中整理url和method,配合CustomStringConvertible输出descriptionMethod已在Alamofire中实现,like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
enum Method: String, CustomStringConvertible {
case OPTIONS = "OPTIONS"
case GET = "GET"
case HEAD = "HEAD"
case POST = "POST"
case PUT = "PUT"
case PATCH = "PATCH"
case DELETE = "DELETE"
case TRACE = "TRACE"
case CONNECT = "CONNECT"

public var description: String {
return self.rawValue
}
}

加一些 “Protocal-Oriented”

从不少开源代码中看到不少这样的使用,在WWDC上也有相关内容,随着自己对swift使用经验的积累,越来越体会到“组合”比之余“继承”的方便之处

从一个常见的使用场景,performSegueWuthIdentifer(identifer: String, sender: AnyObject?)方法,根据不用的identifer执行不同的跳转,原来只能借助于switch语句,由于都是string,很容易写错,那么在swift中呢?

也许可以用enum把identifer装饰一下,避免频繁直接使用字符串,like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
	enum SegueIdentifer: String {
case aaa
case bbb
}

// ...
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
guard let idf = segue.identifer, segueIdf = SegueIdentifer(raValue: idf) else {
fataError("wrong idf:\(segue.identifer)")
}

switch segueIdf {
case .aaa:
// do some thing
case .bbb
// do some thing
}
}

但是跟原先的写法没什么不通,未见的如何swift,如果在别处需要跳转这些代码仍然要重复,怎么办呢?
不如这样:

1
2
3
protocol SegueHeadlerType {
typealias SegueIdentifer: RawRepresentable
}