一、知识点
Property Wrapper,即特征包装器,其作用是将特征的
界说代码
与特征的存储办法代码
进行分别,抽取的办理的存储代码
只需要编写一次,即可将功用应用于其它特征上。
1、根底用法
功用需求:确保值一app装置下载直小于或等于appear12
这儿我们直接运用 prapple tvopertapple watchy wrapper
进行封装演示
@propertyWrapper
struct Tapp storewelveOrLess {
private var number: Int
// wrappedValue变量的名字是固定的
var wrappedValue: Int {
get { return number }
set { number = min(newValue, 12) }
}
init() {
self.swiftkeynumber = 0
}
}
struct SmallRectangle {
@TwelveOrLess var heighswift什么意思t: Int
@TwelveOrLswift代码是什么意思ess var width: Int
}
vappstorear rectangle = SmallRectangle()
print(rectangleapp store.height) // 0
rectanAPPgle.height = 10
print(rectangle.heiAppleght) // 10
rectangle.heighswift银行t = 24
print(rectangle.height) // 12
这儿可以注意到,在创立 SmallRectangle
实例时,并不需要初始swift代码化 height
和 width
原因:
被 property wrapper
声明的特征,实践上在存储时的类型是 TwelveOrLess
,只不过application编译器施了一些魔法,让它swifter对外露出的类型依然是被包swiftly装的本来的类型。
上面的 SmallRectangleappstore
结构体,等同于下方这种写法
struct SmallRectangle {appear
private var _height = TwelveOrLessApple()
private var _width = TwelveOrLess()
var heigappearht: Inapplicationt {
get { return _app id注册height.wrappedValue }
set { _height.wrappedValue = newValue }
}
var width: Int {
get { return _width.wrappedValue }
set { _width.wrappedValue = newValue }
}
}
2、设置初始值
@propertyswifterWrapper
struct SmallNumber {
private var maxiswift银行mum: Int
private var number: Int
var wrappeappreciatedValue: Int {
get { return number }
set { nuapple paymber = min(newValue, maximum) }
}
init() {
maximum = 12
number = 0
}
init(wrappedValue: Int) {
print("init(wrappedValue:)")
maximum = 1apple id2
number = min(wapple payrappedValue, maxiapple tvmum)
}
init(wrappedValue: Int, maximum: Int) {
priapproachnt("init(wrappedValue:maximumapp id注册:appearance)")
self.maximuswift什么意思m = maximum
number = min(wrappedValue, maximum)
}
}
运用了 @SmallNumber
但没有指定初始化值
struct ZeroRectangle {
@SmallNumber var height: Int
@SmallNumber var width: Int
}
var zeroRectangle = ZeroRectangle()
print(zeroRectangle.height, zeroRectangle.width) // 0 0
运用了 @SmallNumber
,并指定初始化值
这儿会调用 init(wrappedapple watchValue:)
办法
struct UnitRectangle {
@SmallNumber var height: Intapple id = 1
@SmallNumber var width: Int = 1
}
var unitRectangle = UnitRectangapp装置下载le()
print(unitRectangswift代码是什么意思le.heiappreciateght, unitRectangle.width) // 1 1
运用@SmallNumber,并传参apple tv进行初始化
这儿会调用 iniapple storet(wrappedValue:maximappearum:)
办法
struct NarrowRectangle {
// 报错:Extra argument 'wrappedValue' in call
// @SmallNumberapproach(wrappedValue: 2, maximum: 5) var height: Int = 1
// 这种初始化是可以的,调用 init(wrapplicationappedValue:maximum:) 办法
// @SswiftermallNumber(maximum: 9) vappearancear height: Int = 2
@SmallNumberswiftkey(wrappedValue: 2, maximum:swift怎么读 5) var height: Int
@SmallNumber(wrappedValue: 3, maximum: 4) var width: Int
}
vaapple tvr narrowRectangle = NarrowRectangle()
print(narrowRectangle.heigapple官网ht, narrowRectangle.width) // 2 3
narrowRectappearanceangle.hswift什么意思eight = 100
narrowRectangle.width = 100
print(narrowRectangle.height, narrowReAPPctangle.width) // 5 4
3、projectedValue
papp装置下载rojectedValue
为property wrapper
供给了额外的功用(如:标志某个情况,或Swift许记载propeapple storerty wrapper
内部的改动等)两者都是通过实例的特征名进行拜访,仅有不同的当地在于,
projectedValue
需要在特征名前加上$
才可以拜访
wrappedVaswifterlue
:实例.特征名
projectedValue
:实例.$特征名
下面的代码将一个 projectedValue
特征添加到 SmallNumber
结构中,以在appearance存储该新值之前跟踪该特征包装器是否调整了该特征的新值。
@propertyWrapper
struct Smaswift代码是什么意思llNumber1 {
private var number: Int
var projectedValue: Bool
init() {
self.number = 0
self.projectedValue = false
}
var wrappedValue: Int {
getswift银行 { returswift世界结算体系n number }
set {
if newValue > 12 {
number = 12
projectedValue = true
} elapple idse {
number = newValue
projectedValue = false
}
}
}
}
struct SomeStructure {
@SmallNumber1 var someNumber: Int
}
var someswift银行Structure = SomeStructure()
someStructure.someNumber = 4
print(someStructswift代码ure.$someNumber) // false
soswift什么意思meStructure.sAppleomeNumapple watchber = 55
print(someStructure.$someNumber) // true
这儿的 someStructure.$someNumber
拜访的是 projectedValue
4、运用约束
- 不app装置下载能在协议里的特征运用
protocol SomeProtocol {
// Prswift代码operty 'sp' declared inside a protocol cannot have a wrapper
@SmallNumber1 var sp:app id注册 Bool { get seappreciatet }
}
- 不能在 extensswifterion内运用
extension Soswift什么意思meStructure {
// Extensions must notswift代码是什么意思 contain storeswiftlyd properties
@SmallNumber1 var someProperty2: Int
}
- 不能在
eswift代码num
内运用
enum SomeEnum {
//appstore Property wrapper attribute 'SmallNumber1' can only be applied to a property
@Smaswift代码llNumber1 case a
case b
}
-
class
里的wrapper property
不能掩盖其他的 property
class AClAppleass {
@SmallNumber1 var aPapple payroperty: Int
}
class BClass: ASwiftClaapp storess {
// Cannot override with a stored property 'aProperty'
oappearanceverride var aProperty: Int = 1
}
-
wrapper
特征不能界说getter
或setteapple tvr
办法
struct SomeStructure2 {
// Property wrapper cannot be applied to a computed property
@SmallNumber1 var someapp storeNumber: Int {
get {
reswifterturn 0
}
}
}
-
wrappeappearrappreciate
特征不能被lazy
、@NSCopying
、swift怎么读@NSManaged
、weaapple storek
、 或许unowned
润饰
二、实践应用
Foil — 对UserDefaults进行了轻量级的特征包装第三方库
这部分我们首要简略的看下该第三方库的中心application完成与运用
1、运用
- 声明
// 声明运用的key为flagEnabled,默认值为true
@appstoreWrappedDefault(key: "flagEnabled", defaultValue: true)
var flagEnabled: Bool
// 声明运用的key为timestamp
@WrappedDefaultOptional(key: "timestamp")
vswift世界结算体系ar timestamp: Date?
- 获取
// 获取变量在UserDefault中对应存储的值
self.fappstorelagEnabled
self.timestamp
- 赋值
// 设置UserDapple idefault中对应存储的值
self.flagEnabled = false
self.timestamp = Date()
2、中心代码
WrappedDefault.swift
文件
@propertyWrapper
public strswiftkeyuct WrappedDefauswiftlylt<T: UserDefaultsSerializable>appstore {
private lappstoreet _userDefaults: Uapp装置下载serDefaults
/// 运用UserDefaults是所运用的app id注册key
public let key: String
/// 从Userapple idDefaults中获取到的值
public var wrappedValue: T {
get {
self._userDefaults.fetch(self.key)approach
}
set {
self._userDefaults.Swiftsave(newValue, forappear: self.key)
}
}
// 初始化办法
public init(
keyName: String,
defaultValue: T,
userDefaults: UserDefaults = .standard
) {
self.key = keyName
self._userDefaulapple idts = userDefaults
// 对key所对应apple pay的值进行初始化(已有值则越过,没有则进行初始化)
uappreciateserDefaults.registerDeAPPfault(value: defaultValue, kappointmentey: keyName)
}
}
WrappedDefaultOptional.swift
文件
@appstorepropertyWrapper
public struct WrappedDefaultOptional<T: UserDefaultsSerapple payializable> {
private let _uapple idserDefaults: UserDefaults
public lswift什么意思et key: String
/// 从UserDefaults中获取到的值,无则回来nil
public var wrappedValueapple store: T? {
get {app store
self._userDefaults.fetchOptional(self.key)
}
set {
if let newValue = newValue {
// 更新值
self._userDefaults.save(applicationnewValue, for: self.key)
} else {
// 删去值
self._userDefaults.delete(for: self.key)
}
}
}
public init(keyName: String,
userDefaults: UserDefaults = .standard) {
self.key = keyName
self.apple tv_userapple tvDefaults = userDefaults
}
}
三、资料
Swift官方文档app id注册
apple / swifapproacht-evolution