关于Swift与OC的不同
· Swift是一门更加现代化的语言,但是目前还在成长阶段,更新改动比较大,虽然说其底层思想不变,变的是API和接口,而且目前Swift开发都要转成OC的runtime,包略大,因此认为成熟项目最好还是采用OC
· 先记住一句话:OC底层面向对象,而Swift底层更加面向协议
· 我们已经见识过Apple使用了大量协议,比如在tableView当中,我们可以通过协议来告诉Apple需要多少个表视图单元格,而不是每时每刻都要继承UITableViewController
· 在这里以MVVM作为测试用例:比如现在需要建立一个类似设置界面的tableView,每个cell需要一个label和一个switch,自定义SwitchWithTextTableViewCell,在其内部建立一个configure方法中对label的title,titleFont,titleColor,switch的switchOn和switchColor等进行初始化,但这种方式非常累赘,比如添加一个副标题,就需要额外添加三个属性
· 但是利用协议SwitchWithTextCellProtocol,让视图模型实现这个协议,然后在这里设置所有的属性
protocol SwitchWithTextCellProtocol {
var title: String { get }
var titleFont: UIFont { get }
var titleColor: UIColor { get }
var switchOn: Bool { get }
var switchColor: UIColor { get }
func onSwitchTogglenOn(onL Bool)
}
· 通过swift2.0重点饿协议扩展,就可以通过默认值来做一些处理了,如果对于大多数单元格来说,可以确定某一种颜色的话,就可以对其建立扩展,然后设置颜色即可,所有实现此协议的视图就没有必要再去设置这个颜色了
· 现在,我的configure方法里面只要实现此协议的值就可以了
// 这个方法只需要一个参数,相比于之前的多个参数简便了很多
class SwitchWithTextTableViewCell: UITableViewCell {
func configure(withDelegate delagate: SwitchWithTextCellProtocol) {
// 在这里配置方法
}
}
· 现在的视图模型
struct MinionModeViewController: SwitchWithTextCellProtocol {
var title = "excellent!!"
var switchOn = true
var switchColor: UIColor {
return .yellowColor()
}
func onSwitchToggleOn(on: Bool) {
if on {
print("The Minions are here to stay!")
} else {
print("The Minions went out to play!")
}
}
}
· 现在,cellForRowAtIndexPath()也变得非常简明了
let cell = tableView.dequeueReuseableCellWithIdentifier("SwitchWithTextTableViewCell", forIndexPath: indexPath) as! SwitchWithTextTableViewCell
cell.configure(withDelegate: MinionModeViewModel())
return cell
再把模型放在视图模型层级,一遍对其进行跟踪,再视图模型中传递这些信息,这样单元格就可以生成了
· 但是在这个基础上,还可以再做进一步的深化,就是建立两个协议,一个作为实际编码的数据源,比如标题内容之类的实际数据,一个作为单元格委托,存储颜色、字体之类的并没有包含实际数据的信息,也就是仿照Apple中UITableView等集合视图之类的地方,按照这种思维去建立单元格存储和单元格委托
protocol SwitchWithTextCellDataSource {
var title: String { get }
var switchOn: Bool { get }
}
protocol SwitchWithTextCellDelegate {
func onSwitchTogglenOn(on: Bool)
var switchColor: UIColor { get }
var textColor: UIColor { get }
var font: UIFont { get }
}
· 接下来,再让configure方法同时接受这两个协议。因为委托可以全部在协议扩展中使用默认值进行配置,比如说字体、颜色之类的信息,这样在理论上就可以不用向里面传递任何东西进去,只需要创建一个模型就可以了
// SwitchWithTextTableViewCell
func configure(withDataSource dataSource: SwitchWithTextCellDataSource, delegate: SwitchWithTextCellDelegate?) {
// 在这里配置视图
}
· 然后就要开始通过扩展来改进视图模型了,使用一个实际数据源的代码块,然后给定要传递的视图当中的原始信息
struct MinionModeViewModel: SwiftWithTextCellDataSource {
var title = "Minion Mode!!"
var switchOn = true
}
· 接下来会在一个单独的视图模型的部分使用处理字体、颜色之类的委托,然后在其中进行相关的配置
extension MinionModeViewModel: SwitchWithTextCellDelegate {
var switchColor: UIColor {
return .yellowColor()
}
func onSwitchToggleOn(on: Bool) {
if on {
print("The Minions are here to stay!")
} else {
print("The Minions went out to play!")
}
}
}
· 最终,表格视图单元格变得非常简单
// SettingViewController
let viewModel = MinionModeViewModel()
cell.configure(withDataSource:viewModel, delegate: viewModel)
return cell
仅仅需要创建视图模型,然后将其传递到配置方法当中,最后返回单元格,就可以了