这是本系列最后一个章节,主要是一些进阶内容的提问和解答,考察的是开发者功力的深厚
之前说一个 iOS 开发者成长到一定阶段,就会遇到瓶颈,解决的方法是熟悉设计模式。接触到 App 的架构App 的架构就类似于现代建筑的脚手架或是地基——一旦确定,App 的骨架和结构就已经定型,剩下的工作就是在现成的架构中舔砖加瓦。那么具体来说,我们为什么要关心 App 的架构?有三点原因。
首先就是代码均摊。试想如果所有代码都集中在一个 UIViewController 中,App 理论上确实能够运行,然而当调试时面对拥有庞大代码的单个文件,我们需要花大量的时间去找到发生问题的源头。同时在修改代码的同时,又因为所有代码都集中在一处,我们必须格外小心,防止一处修改、他处崩溃这种牵一发而动全身的情况出现。这种就像很多团电路交错在一起,即使是熟练的电工也因为过于复杂而觉得无从下手。真正的架构应该合理分配代码,每个类、结构体、方法、变量的存在都应该遵循单一职责原则。
其次是便于测试。测试确保了代码的质量。我们熟知的单元测试、性能测试、UI 测试都是针对单个方法或界面进行测试。架构的合理分配决定了各个测试能够各司其职,不重复、不遗漏,做到最大的测试效率和覆盖率。
最后就是易用性。好的架构确保了日后开发中可以轻松应对各种新需求;即使是新人也可以快速学习并适应现有的架构并进行开发。
本节将围绕目前流行的 MVC,MVP,MVCS,MVVM,VIPER 等架构来展开。由于绝大多数开发者对于部分架构并不熟悉,本节将着重对架构进行特点分析,并在其之间进行横向比较。
关键词:#耦合
MVC 的优点有 2 个:
缺点主要由视图层 和控制器层高度耦合造成,其负面影响主要为:
其实 MVC 的缺点一言以蔽之,就是过于笼统的代码分配。任何一个类或者结构体,只要不是数据或是视图,就被放在了控制器一层,而 ViewController 类耦合了视图和控制器,可以说这是 MVC 架构天生的缺点。
如果你正在跳槽或者正准备跳槽不妨动动小手,添加一下咱们的交流群101 295 1431来获取一份详细的大厂面试资料为你的跳槽多添一份保障。
关键词:#view #model
class User {
var name: String
var avatar: UIImage
init(_ name: String, _ avatar: UIImage) {
self.name = name
self.avatar = avatar
}
}
extension UIImageView {
func configure(with user: User) {
...
}
}
class ViewController: UIViewController {
var user: User?
var userImageView: UIImageView?
override func viewDidLoad() {
super.viewDidLoad()
userImageView = UIImageView()
userImageView.configure(with: user)
}
}
以上代码是经典的 MVC 架构,然而却在两个地方将 View 和 Model 层耦合在了一起。
首先,User 类作为 Model,其内部是不应该有 UIImage 这种视图属性的,可以将其改为 NSData。
其次,userImageView 作为 View 层,是不应该与 Model 层直接接触的。而在 viewDidLoad 中,我们却发现 userImageView 直接可以调用做为 Model 的 User 去进行配置。这个操作应该由 ViewController 去完成
修改后的代码如下:
class User {
var name: String
var avatarData: Data
init(_ name: String, _ avatarData: Data) {
self.name = name
self.avatarData = avatarData
}
}
class ViewController: UIViewController {
var user: User?
var userImageView: UIImageView?
override func viewDidLoad() {
super.viewDidLoad()
userImageView = UIImageView()
configure(userImageView, with: user)
}
func configure(_ imageView: UIImageView?, with user: User) {
...
}
}
关键词:#数据层 #网络层
MVCS 架构其实就是针对 MVC 的优化。S 是 Store 的缩写,意为存储。一般数据持续化层(例如 Core Data )就是 Store,我们把这部分代码单独从 Model 或是 ViewController 里拆分出来构成单独的文件,这就是所谓的数据层。
之前我们提到,MVC 的缺点之一就是网络层无处安放。其实根据 MVCS 这个思路,我们我们也可以把网络层放在 S 这一层中。毕竟网络请求也是获得数据,而且一般 API 请求之后数据都要做缓存和持久化处理,所以放在 S(数据层)来说也比较合理。
拆分出来之后,整个代码分配更加均衡。同时以往在 ViewController 里面难以进行的单元测试也可以根据单独的数据层文件进行测试,总体来讲测试覆盖率会有所提高。整个拆分之后对于整体架构的维护和扩展也起到了促进作用。
关键词:#解耦 #代码量
MVP 的全称是 Model-View-Presenter。它和 MVC 的相同点在于:两者的 Model 功能一样,理论上来讲两者的 Model 层应该完全一样。
而不同点在于,MVC 中 View 和 Controller 耦合在 ViewController 类里;而 MVP 的 View 是单独的 UIView/UIViewController,Presenter 也是单独的类。我们来看下 MVP 的结构:
如图,MVP 中的 View 是单独的 Class(在 MVP 中,UIView 或是 UIViewController 都属于 View 层),它持有 Presenter 作为变量。当接收到用户交互时,它会调用 Presenter 进行处理。也就是说,View 层不包含任何的业务逻辑代码,它只会将交互交给 Presenter,并从 Presenter 那里接受结果来更新自己。
如果你正在跳槽或者正准备跳槽不妨动动小手,添加一下咱们的交流群101 295 1431来获取一份详细的大厂面试资料为你的跳槽多添一份保障。
而 MVP 中的 Presenter 则负责业务逻辑,它是 View 和 Model 的桥接。它会根据 View 中的交互去修改 Model,或根据 Model 的变化去修改 View。
这里要注意,因为 View 持有 Presenter,所以 Presenter 中的 View 应该声明为 weak 或 unowned,以避免循环引用。
相比于 MVC,MVP 的耦合度大大降低,代码分配更加合理,测试起来非常方便,整个架构理解和上手难度也并不高。
但是它的缺点在于,View 的所有交互都要传给 Presenter 去处理,这样就项目功能一旦增加,View 的代码和 Presenter 的代码都会增加。相比于 MVC 在 ViewController 一个文件里面直接解决,MVP 的总代码量可能会翻倍,这样 App 的维护成本和文件大小都会增大。
关键词:#数据提供 #交互响应
ViewModel 一般来扮演两个重要角色:
注意 ViewModel 类中绝对不能包含视图层的任何类或结构体。MVVM 的示意图如下:
关键词:#模型层 #中间层 #视图层
MVC、MVP、MVVM 三种架构皆由模型层(M - Model),视图层(V - View),中间层(C/P/VM - Controller/Presenter/View Model)构成。我们的比较就先从局部开始——分别比较这三个部分,再到整体差异。
但理论上来说,MVC 是希望视图层就是单纯的 UIView,或者 UIViewController 只负责 UI 更新交互,不涉及业务逻辑和模型更新。
MVP 和 MVVM 在实际开发中视图层实现了 MVC 理论期望,即与中间层严格分离。
MVP 中视图层是完全被动,单纯的把交互和更新传递给中间层;而 MVVM 中视图层并不是完全被动——它会监视中间层的变化,一旦产生变化,则视图层也会相应变化。
MVC 的中间层 Controller 持有视图和模型,主要起到一个组装和连接的作用,通过传递参数和实例变量来直接完成所有操作。
MVP 的中间层 Presenter 持有模型,在更新模型上与 MVC 的 Controller 角色一样。但它不拥有视图,视图拥有中间层,中间层的工作流程是:从视图层接收交互传递->响应->向视图层传递响应指令->视图进行更新。全部操作必须手动书写代码完成。
MVVM 的中间层 View Model 持有模型,在更新模型上与前两者相同。它完全独立于视图,视图拥有中间层,通过绑定属性,自动进行更新。全部操作由响应式逻辑框架自动完成。
关键词:#路由 #Interactor
VIPER 架构分别由 5 部分组成:View, Interactor, Presenter, Entity, Router。它的示意图如下,我们从左向右依次来看:
由于分工明确,VIPER 层在代码分配、测试覆盖率上为所有架构之冠。
缺点在于,它依然与 MVX 架构一样,是个视图驱动的架构。同时,由于分工精细,不同层级之间交互的代码很多,总体代码量很大,不适宜用在小型 App 中。
iOS开发人群越来越少,说实在的,每次在后台看到一些读者的回应都觉得很欣慰,至少你们依然坚守iOS技术岗…为了感谢读者们,我想把我收藏的一些编程干货贡献给大家,回馈每一个读者,希望能帮到你们。
干货主要有:
① iOS中高级开发必看的热门书籍(经典必看)
② iOS开发技术进阶教学视频
③ BAT等各个大厂iOS面试真题+答案.PDF文档
④ iOS开发中高级面试"简历制作"指导视频
如果你用得到的话可以直接拿走;如何获取,具体内容请转看-我的GitHub
我的:GitHub地址
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。