XiaoboTalk

swift 属性

一: 存储属性

非 lazy 型的属性,必须在自己的 init 完成之前,完成初始化。
1、直接赋值:
let attr: Int = 1
2、用自执行的 closure 赋值
// 当初始化工作有多个属性要设置的时候,用 closure 更合适 let attr: Int = { let x = 1 + 2 return x }() // 上边等同于 先定义,然后在 init 中赋值 see: https://stackoverflow.com/questions/35065649/are-computed-properties-evaluated-every-time-they-are-accessed let attr: Int init() { self.attr = 1 super.init() }
总之,存储属性,要求在 init 之前完成赋值,除非是可选类型。可空类型,可以不必赋值
var op: Int?
3、lazy 型
第一次访问时创建:
private(set) lazy var imageView: UIImageView = { let view = UIImageView() view.contentMode = .scaleAspectFit view.backgroundColor = .clear return view }()
4、willSet didSet 监听属性值得变化
调用的时候,先子类,后父类.
class Test { var property1: String = "aaa" { // 设置值之前监听,参数为新值 willSet { // 默认参数名 newValue print("Test property will set: \(newValue)") } didSet { // 默认参数名是 oldValue print("Test property will set: \(oldValue)") } } } class SubTest: Test { override var property1: String { willSet { print("SubTest property will set") } } } let subTest = SubTest() subTest.property1 = "bbb" // output: // SubTest property will set // Test property will set

二: 计算属性

本身就有个 set get, 因此不需要 willSet/didSet。计算属性,事实上是一个 closure,在语法上 计算属性只通过声明式的语法进行定义,这也区别于了存储属性。
struct Point { var x = 0.0, y = 0.0 } struct Size { var width = 0.0, height = 0.0 } struct Rect { var origin = Point() var size = Size() // 计算属性 center ,注意语法上没有用 = 进行赋值,而只是用声明的语法格式 var center: Point { get { let centerX = origin.x + (size.width / 2) let centerY = origin.y + (size.height / 2) return Point(x: centerX, y: centerY) } set(newCenter) { origin.x = newCenter.x - (size.width / 2) origin.y = newCenter.y - (size.height / 2) } } }

三、在 extension 中增加存储属性

默认 swift extension 支持计算属性,但不支持存储属性,可以用类似 oc 的方式,进行绑定。Swift 4 之后,可以用内部 struct 结合计算属性实现。不过这种方式有个致命的问题,因为 struct 中用的是 static 变量,静态属性,不管多少个实例都是同一个值。
extension ExtClass: OriginalClass { struct Dragger { static var offset: Double = 0.0 static var startX: Double = 0.0 } var draggingOffset: Double { get { return Dragger.offset } set { Dragger.offset = newValue } } }