ViewStyle 1.0.0

ViewStyle 1.0.0

测试已测试
Lang语言 SwiftSwift
许可 MIT
发布上次发布2017年2月
SwiftSwift 版本3.0
SPM支持 SPM

Minya 维护。



ViewStyle 1.0.0

ViewStyle

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,并且样式具有相同的属性,那么设置将覆盖之前的设置。

KVC 和非 KVC

ViewStyle 通过 KVC 大量设置属性。但是,某些属性不是 KVC,这些属性需要特殊处理。您可以在 UIView 或其子类的 mi_specialProperties 属性中指定这些属性,然后在 mi_setValue(_:forKey:) 方法中逐个设置这些属性的值。

注意:在 UIView 子类中重写 mi_setValue(_:forKey:) 方法时,务必调用超类的 mi_setValue(_:forKey:) 方法,以确保继承链中的所有非 KVC 属性都得到正确设置。

调试模式下的检测

在调试模式下,有两种检测

  1. 检查类是否包含所有属性。然而,不包括非 KVC 属性或键路径属性,例如 UIView 的 layer.borderColor。您必须确保这些属性的正确性。
  2. 检查值的类型是否正确。

我们在检测的第二步中做了一些特殊处理。

  1. 某些属性的实际情况与文档中的类型不同,例如文档中某些颜色属性的类型为UIColor,但实际上是UICachedDeviceRGBColor。我们对此类类型进行了映射,以便进行检测。
  2. 使用setValue(forKey:)设置值时,数值类型没有区别,因此我们统一处理数值类型。
  3. 某些CG类型(如CGColorCGPath)的原始类型是__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属性和UIViewmi_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中存在一些明显的问题

  1. 它不用于布局;
  2. mi_styles的类型为[Property: Any],而value的类型为Any,因此无法进行编译时类型检测。你必须确保所有值类型的正确性。
  3. 你需要使用mi_specialProperties属性和mi_setValue(_:forKey:)方法检查非KVC属性。

安装

需求

此库需要iOS 8.0或更高版本。

LICENSE

ViewStyle提供在MIT许可证下。请参阅LICENSE文件以获取详细信息。