Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Property Wrappers

Avatar for Swift India Swift India
November 16, 2019

Property Wrappers

Avatar for Swift India

Swift India

November 16, 2019
Tweet

More Decks by Swift India

Other Decks in Technology

Transcript

  1. Scope of Discussion • What are Property wrappers • Motivation

    behind Property wrappers • Glimpse on the evolution • Some uses of Property wrappers • Frameworks where they are used today • Future proposals
  2. Property Wrapper? • Property Wrapper is a generic data structure

    that wraps a property and specifies its access patterns. • Intended to remove boiler plate code that we write for custom getters and setters.
  3. Proposal • Proposed as Property Behaviours. • Remove boiler plate

    code written for access patterns. • Remove inconsistencies of @NSCopying. • Aimed at addressing problem of repeated property patterns like lazy. Dec, 2015
  4. • Proposal rejected sighting immaturity of Swift. • Swift was

    changing rapidly with changes in core APIs. Feb, 2016
  5. • Pitch #2 was submitted in March 2019. • Inspired

    and refined with inspiration from Delegated Properties in Kotlin. • Known as Property Delegates. • Pitch #3 was submitted in May 2019. • Initializer renamed. • Name was changed to Property Wrappers. • Syntax refined.
  6. Syntax @propertyWrapper struct PropertywrapperName<T> { var projectedValue = Something //

    Additional API that can exposed additional data var wrappedValue: T { get { // Custom logic for getter } set { // Custom logic for setter } } init(wrappedValue: T) {...} init(wrappedValue: T = Initial Value, additional params) {...} }
  7. • Minimum Value • Current value • Flexi interest Current

    value = current value + (interest)% * current value Growth = (current value > min value) ? Appreciating : depreciating
  8. struct WalmartFoodBond { var bondValue: Int { set { bondCurrentWorth

    = newValue + (newValue * flexiInterest/100) growth = bondCurrentWorth < minimumValue ? .depriciating : .appreciating } get { bondCurrentWorth } } private (set ) var bondName: String private (set ) var growth: BondGrowth = .appreciating private var bondCurrentWorth: Int private var flexiInterest: Int private var minimumValue: Int init(bondName: String, minimumValue: Int, flexiInterest: Int, value: Int) { self.bondName = bondName self.minimumValue = minimumValue self.bondCurrentWorth = value self.flexiInterest = flexiInterest self.wrappedValue = value } }
  9. @propertyWrapper struct BondValue { private var bondCurrentWorth: Int private var

    minimumValue: Int private var flexiInterest: Int var projectedValue: BondGrowth = .appreciating // The projected value projects the growth for the bond var wrappedValue: Int { get { return bondCurrentWorth } set { bondCurrentWorth = newValue + (newValue * flexiInterest/100) projectedValue = bondCurrentWorth < minimumValue ? .depriciating : .appreciating } } init(wrappedValue: Int = 0, minimumValue: Int, flexiInterest: Int) { self.minimumValue = minimumValue self.flexiInterest = flexiInterest self.bondCurrentWorth = wrappedValue } }
  10. struct WalmartFoodBond { var bondName: String @BondValue(minimumValue: 0, flexiInterest: 0,

    value: 0) var bondValue = 0 init(bondName: String, minimumValue: Int, flexiInterest: Int, value: Int) { self.bondName = bondName _bondValue = BondValue(minimumValue: minimumValue, flexiInterest: flexiInterest) } } struct WalmartCommerceBond { var bondName: String @BondValue(minimumValue: 0, flexiInterest: 0, value: 0) var bondValue = 0 init(bondName: String, minimumValue: Int, flexiInterest: Int, value: Int) { self.bondName = bondName _bondValue = BondValue(minimumValue: minimumValue, flexiInterest: flexiInterest) } }
  11. var foodBond = WalmartFoodBond(bondName: "Walmart Food Bond", minimumValue: 200, flexiInterest:

    10, value: 200) print("Walmart Food Bond current worth - \(foodBond.bondValue)") print("Walmart Food Bond growth - \(foodBond.$bondValue)”) var commerceBond = WalmartCommerceBond(bondName: "Walmart Growth Bond", minimumValue: 200, flexiInterest: 10, value: 200) print("Walmart Commerce Bond current worth - \(commerceBond.bondValue)") print("Walmart Commerce Bond growth - \(commerceBond.$bondValue)”) commerceBond.bondValue = 50 print("Walmart Commerce Bond final growth - \(commerceBond.$bondValue)”) OUTPUT: Walmart Food Bond current worth - 220 Walmart Food Bond growth - appreciating Walmart Commerce Bond current worth - 220 Walmart Commerce Bond growth - appreciating Walmart Commerce Bond final growth - depriciating
  12. Use cases of Property Wrappers • Accessing user default values.

    • Implementing custom lazy and NSCopying wrappers. • Guaranteeing access of properties from a particular thread. • Lots many ……
  13. Alternate Proposals • Single protocol 
 protocol PropertyWrapper { associatedtype

    Value var wrappedValue: Value { get } } • Kotlin like by- syntax. • Alternative spellings for the $projection property.
  14. Cavets • Code base can be messy with lot of

    “@“ syntaxes. • “@“ is not a Swifty convention. • Not a developer friendly readable format.
  15. Future Proposals • Finer grained access control
 @SomeWrapper public public(storage)

    private(projection) var foo: Int = 1738 • Referencing the enclosing `self` in a wrapper type. • Delegating to an existing property.