对于iOS开发而言 始终没法绕开UIKit
这个框架, 加之SwiftUI
并不成熟, 因此你懂的, 而UIKit
框架就是基于的MVC
的设计模式, 因此这也是为何MVC
是苹果官方推荐的设计模式.git
一. 官方推荐
这个标签确定是有必定份量的.github
二. 在一个基于MVC的框架上强行使用MVVM或MVP的设计模式, 不是不能够, 但总有些地方会差强人意, 当你使用各类知名框架时就会体会到这种感受, 固然你能够选择忽略不计, 但它们确实存在.swift
三. 简单, 很是的简单, 没有学习成本, 是个开发者就懂, 基本没有"交流"障碍. 越简单越利于维护(这也是我比较推崇的开发风格 一切从简).设计模式
四. 可扩展性强, 由于足够通用, 因此在MVC基础上能够根据具体业务须要转变成其余设计模式, 总的来讲 整个项目的基础设计模式仍是MVC, 根据不一样业务模块状况能够再使用最合适的设计模式.框架
没错 臃肿的C层代码. 因此不少优化方案都是围绕这点展开的, 我们也不例外.ide
UIViewController
在实际开发中会遇到不少问题, 这里咱们只说View相关的问题.布局
按照苹果的设计理念: UIViewController
对应MVC
的C
, UIView
对应MVC
的V
, XXXModel
对应MVC
的M
.学习
但尴尬的是 咱们使用UIViewController
时 难免会有不少View的处理在其中, 纯代码的方式还好一些, 能够经过封装自定义View类来解决, Storyboard
和Xib
的方式就尤其明显了.优化
纯代码:ui
自定义View类来编写视图相关的代码, 能够将V的处理从UIViewController
中分离出去, 可是难免要在UIViewController
中再次编写初始化 布局等代码. 试想每一个UIViewController
都要写一遍某个View的初始化 添加父视图 布局等.
Storyboard或XIB:
拖线连接的控件一般会在UIViewController
中, 常常见到UIViewController
中拖了一堆视图控件对象. 固然除了拖进来还要写一下其余视图相关的代码. 也有使用自定义View类来承载全部拖线连接的控件对象 和上面纯代码的方式差很少.
一样的困境: 在UIViewController
中view的类型永远都是UIView
, 上面两种方式遇到的问题同样, 须要作类型转换才能访问到自定义View类中的属性和方法, 这无疑是很麻烦的.
ViewController
基类, 并保证基类的干净, 这是一个很好的习惯)class ViewController<Container: UIView>: UIViewController {
var container: Container { view as! Container }
override func loadView() {
super.loadView()
if view is Container {
return
}
view = Container()
}
}
复制代码
class HomeController: ViewController<HomeView> {
override func viewDidLoad() {
super.viewDidLoad()
}
}
复制代码
container
属性直接访问上面声明的自定义View类型对象, 固然你也能够改成其余名字class XXXXController: ViewController<XXXXView> {
// CODE
override func viewDidLoad() {
super.viewDidLoad()
// CODE
container.xxxx()
}
}
复制代码
纯代码:
class XXXXView: UIView {
private lazy var titleLabel = UILabel()
private lazy var iconImageView = UIImageView()
override init(frame: CGRect) {
super.init(frame: frame)
titleLabel.textColor = .black
titleLabel.font = .systemFont(ofSize: 13, weight: .semibold)
iconImageView.contentMode = .scaleAspectFill
addSubview(titleLabel)
addSubview(iconImageView)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
titleLabel.frame = .init(x: 100, y: 100, width: 100, height: 40)
iconImageView.frame = .init(x: 100, y: 100, width: 100, height: 100)
}
func set(title: String) {
titleLabel.text = title
}
func set(image: UIImage) {
iconImageView.image = image
}
}
复制代码
class XXXXController: ViewController<XXXXView> {
private let model = XXXXModel()
// CODE
override func viewDidLoad() {
super.viewDidLoad()
// CODE
container.set(title: model.title)
container.set(image: model.image)
}
}
复制代码
let controller = XXXXController()
present(controller, animated: true)
复制代码
Storyboard或XIB:
设置Controller类:
设置View类:
向View中拖线连接:
在Controller中为视图设置数据:
方法简单, 很好的解决了上面提到的这些问题, 使Controller与View的分离更加优雅.
class HomeController: ViewController<HomeView> { }
复制代码
头部的声明能够直观的看到Controller的View类型, 可读性强.
因明确了类型 调用更加顺畅天然, 省去了多余的类型转换代码.
使 Controller 能够更专一于Model与View的协调和调用, 职责更明确.
截止如今, 这个方法我本身已经使用2年了 其中也经历了几个项目的洗礼, 仍是没什么问题的, 你们若是感兴趣能够放心采纳.
若是你有更好的想法 欢迎评论交流.