swift屬性包裝器 propertyWrapper
什么是屬性包裝器「propertyWrapper」帚湘?
在類军洼、結(jié)構(gòu)體或者枚舉的聲明時使用該特性巩螃,可以讓其成為一個屬性包裝器。如果將該特性應(yīng)用在一個類型上匕争,將會創(chuàng)建一個與該類型同名的自定義特性避乏。將這個新的特性用于類、結(jié)構(gòu)體甘桑、枚舉的屬性拍皮,則可以通過包裝器的實(shí)例封裝對該屬性的訪問歹叮。局部和全局變量不能使用屬性包裝器。
包裝器必須定義一個 wrappedValue 實(shí)例屬性铆帽。該屬性 wrapped value 是該屬性存取方法暴露的值咆耿。大多數(shù)時候,wrappedValue 是一個計算屬性爹橱,但它可以是一個存儲屬性萨螺。包裝器負(fù)責(zé)定義和管理其包裝值所需的任何底層存儲。編譯器通過在包裝屬性的名稱前加下劃線(_)來為包裝器的實(shí)例提供同步存儲宅荤。例如屑迂,someProperty 的包裝器存儲為 _someProperty。包裝器的同步存儲具有 private 的訪問控制級別冯键。
擁有屬性包裝器的屬性可以包含 willSet 和 didSet 閉包惹盼,但是不能重寫編譯器合成的 get 和 set 閉包。
Swift 為屬性包裝器的構(gòu)造函數(shù)提供了兩種形式的語法糖惫确∈直ǎ可以在包裝值的定義中使用賦值語法,將賦值語句右側(cè)的表達(dá)式作為值傳遞給屬性包裝器構(gòu)造函數(shù)中的 wrappedValue 參數(shù)改化。同樣的掩蛤,你也可以為包裝器提供一些參數(shù),這些參數(shù)將會傳遞給包裝器的構(gòu)造函數(shù)陈肛。就像下面的例子揍鸟,SomeStruct 中,定義 SomeWrapper 的地方各自調(diào)用了對應(yīng)的構(gòu)造函數(shù)句旱。
我們先定義一個Limit的屬性包裝器阳藻,用來限制dog的height和weight
@propertyWrapper
struct Limit{
private var number: Int
private var maximum: Int
private var minimum: Int
var projectedValue: String{
return String(describing: "The value: \(self.number)")
}
var wrappedValue: Int{
get { return number }
set {
if (minimum...maximum).contains(newValue){
number = newValue
}else{
number = minimum
print("設(shè)置的值不合理,系統(tǒng)已經(jīng)為您更改為默認(rèn)的最小值")
}
}
}
init() {
minimum = 0
maximum = 0
number = 0
}
init(minimum: Int, maximum: Int) {
self.maximum = maximum
self.minimum = minimum
self.number = minimum
}
init(minimum: Int, maximum: Int, number: Int) {
self.maximum = maximum
self.minimum = minimum
self.number = number
self.wrappedValue = self.number
}
}
然后去使用這個包裝器
struct DogSize{
@Limit(minimum: 10, maximum: 50) var height: Int
@Limit(minimum: 0, maximum: 50) var weight: Int
}
struct Dog{
var size: DogSize
var name: String
}
let dogSize = DogSize()
var dog = Dog(size: dogSize, name: "tom")
dog.size.height = 500
print(dog.size.$height)
print(dog.size.height)
// 設(shè)置的值不合理谈撒,系統(tǒng)已經(jīng)為您更改為默認(rèn)的最小值
// The value: 10
// 10