Cla*_*ges 1 swift swift5 property-wrapper
我需要一个 Swift 属性,如果该值尚未设置,则默认为另一个值。
\n\n这可以使用后备存储私有属性来实现。例如,对于num应该默认为 global 的属性defaultNum,它的工作方式如下:
var defaultNum = 1\n\nclass MyClass {\n var num: Int {\n get { _num ?? defaultNum }\n set { _num = newValue }\n }\n\n private var _num: Int?\n}\n\nlet c = MyClass()\nprint("initial \\(c.num)") // == 1 \xe2\x9c\x85\n\n// changing the default changes the value returned\ndefaultNum = 2\nprint("dynamic \\(c.num)") // == 2 \xe2\x9c\x85\n\n// once the property is set, returns the stored value\nc.num = 5\nprint("base \\(c.num)") // == 5 \xe2\x9c\x85\nRun Code Online (Sandbox Code Playgroud)\n\n这可行,但对于我们代码中的常见模式,每个此类属性都有很多样板。
\n\n使用 Swift 属性包装器,是否可以更简洁地做到这一点?
\n\n请注意,因为我们希望默认值是动态的,所以静态初始化器将不起作用。例如:
\n\nvar defaultNum = 1\n\nclass MyClass {\n var num = defaultNum\n}\n\nvar c = MyClass()\ndefaultNum = 2\nprint(c.num) // this == 1, we want the current value of defaultNum, which == 2\nRun Code Online (Sandbox Code Playgroud)\n
您可以通过创建如下属性包装器来做到这一点:
\n\n@propertyWrapper\npublic struct Default<T> {\n var baseValue: T?\n var closure: () -> T\n\n // this allows a nicer syntax for single variables...\n public init(_ closure: @autoclosure @escaping () -> T) {\n self.closure = closure\n }\n\n // ... and if we want to explicitly use a closure, we can.\n public init(_ closure: @escaping () -> T) {\n self.closure = closure\n }\n\n public var wrappedValue: T {\n get { baseValue ?? closure() }\n set { baseValue = newValue }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n然后,您可以对@Default属性使用属性包装器,如下所示:
var defaultNum = 1\n\nclass MyClass {\n @Default(defaultNum)\n var num: Int\n}\nRun Code Online (Sandbox Code Playgroud)\n\n然后您会在实践中看到以下内容:
\n\nlet c = MyClass()\n\n// if we haven\'t set the property yet, it uses the closure to return a default value\nprint("initial \\(c.num)") // == 1 \xe2\x9c\x85\n\n// because we are using a closure, changing the default changes the value returned\ndefaultNum = 2\nprint("dynamic \\(c.num)") // == 2 \xe2\x9c\x85\n\n// once the property is set, uses the stored base value\nc.num = 5\nprint("base \\(c.num)") // == 5 \xe2\x9c\x85\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
943 次 |
| 最近记录: |