ViewStyle
为 iOS 中视图的样式提供了一种类似 CSS 的设置方式。
Web 前端的一般结构是使用 HTML 组织视图的基本结构,使用 CSS 设置 HTML 的显示样式。在 iOS 中,如果您不使用 Interface Builder 而直接用代码绘制 UI,您需要手动设置视图样式。就像 HTML 和 CSS 一样,ViewStyle
的目的是将视图结构和样式代码分离。
通常,我们将设置如下:
tableView = UITableView(frame: self.view.bounds)
tableView!.dataSource = self
tableView!.delegate = self
tableView!.register(UITableViewCell.self, forCellReuseIdentifier: "TableViewCell")
tableView!.rowHeight = 60.0
tableView!.separatorStyle = UITableViewCellSeparatorStyle.singleLine
tableView!.separatorColor = UIColor.lightGray
tableView!.backgroundView = UIView()
tableView!.separatorInset = UIEdgeInsets(top: 10.0, left: 5.0, bottom: 3.0, right: 10.0)
tableView!.cellLayoutMarginsFollowReadableWidth = true
self.view.addSubview(tableView!)
当有大量视图需要设置时,它会有点复杂。在这种情况下,我们可能需要考虑将样式设置的代码分离出来。 ViewStyle
为 UIView 提供了一个 mi_styles
属性,可以设置一些基本样式,如下所示:
class ViewController: UIViewController {
var tableView: UITableView?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// ...
tableView = UITableView(frame: self.view.bounds)
tableView!.dataSource = self
tableView!.delegate = self
tableView!.register(UITableViewCell.self, forCellReuseIdentifier: "TableViewCell")
tableView!.mi_styles = self.tableViewStyle
self.view.addSubview(tableView!)
}
}
// MARK: - Table View Style
extension ViewController {
var tableViewStyle: [Property: Any] {
return [
.rowHeight: 60.0,
.separatorStyle: UITableViewCellSeparatorStyle.singleLine,
.separatorColor: UIColor.lightGray,
.backgroundView: UIView(),
.separatorInset: UIEdgeInsets(top: 10.0, left: 5.0, bottom: 3.0, right: 10.0),
.cellLayoutMarginsFollowReadableWidth: true
]
}
}
定义样式有两种方式
根据实际情况。
注意:如果您为同一视图设置了多个
mi_styles
,并且样式具有相同的属性,那么设置将覆盖之前的设置。
ViewStyle
通过 KVC 大量设置属性。但是,某些属性不是 KVC,这些属性需要特殊处理。您可以在 UIView 或其子类的 mi_specialProperties
属性中指定这些属性,然后在 mi_setValue(_:forKey:)
方法中逐个设置这些属性的值。
注意:在 UIView 子类中重写
mi_setValue(_:forKey:)
方法时,务必调用超类的mi_setValue(_:forKey:)
方法,以确保继承链中的所有非 KVC 属性都得到正确设置。
在调试模式下,有两种检测
layer.borderColor
。您必须确保这些属性的正确性。我们在检测的第二步中做了一些特殊处理。
UIColor
,但实际上是UICachedDeviceRGBColor
。我们对此类类型进行了映射,以便进行检测。setValue(forKey:)
设置值时,数值类型没有区别,因此我们统一处理数值类型。CGColor
或CGPath
)的原始类型是__NSCFType
。我们不会仔细检查它们。在调试模式下,如果这些检测中的任何一个失败,将会执行断言处理。
在ViewStyle
中,如果你想为视图类添加一个属性,可以扩展Property
结构体,并按以下方式添加属性:
// UITextField+Style
extension Property {
public static let borderStyle = Property(#keyPath(UITextField.borderStyle), .textBorderStyle)
public static let background = Property(#keyPath(UITextField.background), MIType.image>?)
public static let disabledBackground = Property(#keyPath(UITextField.disabledBackground), MIType.image>?)
public static let clearButtonMode = Property(#keyPath(UITextField.clearButtonMode), .textFieldViewMode)
}
对于非KVC属性,你必须做一些特殊的工作。覆盖mi_specialProperties
属性和UIView
的mi_setValue(_:forKey:)
方法,如下所示:
// MARK: - Special Attributes
extension UITextField {
open override var mi_specialProperties: [String] {
var properties = super.mi_specialProperties
properties.append(contentsOf: [
#keyPath(UITextField.textAlignment),
])
return properties
}
open override func mi_setValue(_ value: Any, forKey key: String) {
switch key {
case #keyPath(UITextField.textAlignment):
self.textAlignment = value as! NSTextAlignment
default:
super.mi_setValue(value, forKey: key)
}
}
}
理论上,您可以添加任何需要的属性,而不仅仅是显示属性。
ViewStyle
中存在一些明显的问题
mi_styles
的类型为[Property: Any]
,而value
的类型为Any
,因此无法进行编译时类型检测。你必须确保所有值类型的正确性。mi_specialProperties
属性和mi_setValue(_:forKey:)
方法检查非KVC属性。此库需要iOS 8.0或更高版本。
ViewStyle提供在MIT许可证下。请参阅LICENSE文件以获取详细信息。