property wrapper
(翻译为中文叫做特点包装器)能够为代码添加了一个层阻隔,这层阻隔是针对property的,添加的方位是:property的界说代码和property如何存储的代码之间
更简单浅显一点的描绘是:
在
property
的存和取的进程中添加了一些代码,这些代码逻辑便是Property Wrapper
Property Wrapper根本写法与作业原理
-
@propertyWrapper
标记 + (class或struct或enum)来界说一个Property Wrapper
- 该结构中有必要声明一个
wrappedValue
特点,用于表明包装后的值
@propertyWrapper
struct TwelveOrLess {
private var number = 0
var wrappedValue: Int {
get { return number }
set { number = min(newValue, 12) }
}
}
struct SmallRectangle {
@TwelveOrLess var height: Int
@TwelveOrLess var width: Int
}
rectangle.height = 24
print(rectangle.height)
// Prints "12"
根本原理是,编译器会主动将Property Wrapper中的逻辑组成到每个使用的特点上,经过显式的Property Wrapper写法能够看出大致的作业原理
struct SmallRectangle {
private var _height = TwelveOrLess()
private var _width = TwelveOrLess()
var height: Int {
get { return _height.wrappedValue }
set { _height.wrappedValue = newValue }
}
var width: Int {
get { return _width.wrappedValue }
set { _width.wrappedValue = newValue }
}
}
Property Wrapper高档用法
现在咱们再去审视Property Wrapper,能够更浅显易懂地描绘一下它的作业原理:
在property的set和get进程中,引进一个中间层,这个中间层能够是class、struct或enum中的恣意结构。在这个结构中能够参加恣意逻辑
Property Wrapper
的核心既然是这个中间层,那环绕中间层的界说,出现了一些Property Wrapper
的高档用法
这些高档用法主要是来自Property Wrapper
的不同初始化办法。那么Property Wrapper
有几种初始化办法呢?
因为Property Wrapper
能够用class、struct、enum
恣意类型表明,那初始化办法依照对应type写即可。但是,其中有一种初始化办法比较特别—类似init(wrappedValue:)
,即初始化办法中包含wrappedValue
参数的情况
所以,下面咱们据此分成两类初始化办法进行描绘
- 系统默许或自界说初始化办法
- 有
wrappedValue
参数的初始化办法
自界说初始化办法
@propertyWrapper
struct SmallNumber {
private var maximum: Int
private var number: Int
var wrappedValue: Int {
get { return number }
set { number = min(newValue, maximum) }
}
init() {
maximum = 12
number = 0
}
}
struct NarrowRectangle {
@SmallNumber var number: Int
}
- 上面代码中
SmallNumber
供给了一个初始化办法 -
NarrowRectangle
中number
的写法,便是使用了上述初始化办法 - 注意一点,因为使用了
SmallNumber
初始化办法,所以能够认为默许情况下,NarrowRectangle.number
是被赋值为0的,所以let abc = NarrowRectangle()
写法是不会编译报错的,因为number
能够被正确初始化
有wrappedValue
参数的初始化办法
@propertyWrapper
struct SmallNumber {
private var maximum: Int
private var number: Int
var wrappedValue: Int {
get { return number }
set { number = min(newValue, maximum) }
}
init() {
maximum = 12
number = 0
}
init(wrappedValue: Int) {
maximum = 12
number = min(wrappedValue, maximum)
}
init(wrappedValue: Int, maximum: Int) {
self.maximum = maximum
number = min(wrappedValue, maximum)
}
}
struct UnitRectangle {
@SmallNumber var height: Int = 1
@SmallNumber var width: Int = 2
@SmallNumber(wrappedValue: 2, maximum: 5) var height: Int // 3
@SmallNumber(maximum: 9) var width: Int = 2 // 4
}
- 参数中有
wrappedValue
参数时,为wrappedValue
传参的办法比较特别—此处@SmallNumber var height: Int = 1
的写法就时将1作为wrappedValue
进行传值 - 原理上讲的话,就等价于
UnitRectangle(height: SmallNumber(wrappedValue: 1), width: SmallNumber(wrappedValue: 2))
- 还有更杂乱的初始化,比方后面两种初始化办法
-
UnitRectangle
中3和4写规律使用了第3个初始化办法
总结
-
Property Wrapper
在property的存取进程中添加了一个中间层,能够增加自界说逻辑 -
Property Wrapper
能够将重复代码进行抽离、复用 -
Property Wrapper
的作业原理是编译器主动组成代码 -
Property Wrapper
的作业原理要求property有必要是var
的 - 基于
Property Wrapper
原理能够使用于杂乱的场景,比方简化Codable
进程–参阅CodableWrapper
和ExCodable
代码库