Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initialise property wrapper with dynamic values in Swift 5

Scenario:

  1. I want to have different types of Bonds which has a minimum value, flexi interest current bond worth(calculated on basis of some logic) and bond growth prediction.

  2. Whenever bond value goes more than minimum value, then the growth prediction becomes appreciating and depreciating in vice versa.

  3. I can have multiple bonds with their own set of values.

I am trying to use property wrappers for the same so that I do not replicate the same behaviour for every bond:

 @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, value: Int) {
        self.minimumValue = minimumValue
        self.flexiInterest = flexiInterest
        self.bondCurrentWorth = value
    }
}

No for creating any bond, I do:

struct FoodBond {
    var bondName: String
    @BondValue(minimumValue: 200, flexiInterest: 30, value: 200) var value = 30

    init(bondName: String, minimumValue: Int, flexiInterest: Int, value: Int) {
        self.bondName = bondName
    }
}

Problem statement: - I am not able to initialise the bondvalue with dynamic values.

Possible workaround: I would use the same approach as a normal struct in the below implementation. Though this way of using property wrapper is also specified in the docs, but I would loose the syntactic flavour of the property wrappers.

You could write code that uses the behavior of a property wrapper, without taking advantage of the special attribute syntax. For example, here’s a version of SmallRectangle from the previous code listing that wraps its properties in the TwelveOrLess structure explicitly, instead of writing @TwelveOrLess as an attribute

@propertyWrapper
struct BondValue {
    private (set) var bondCurrentWorth: Int
    private (set) var minimumValue: Int
    private (set) var flexiInterest: Int

    var projectedValue: BondGrowth = .appreciating // The projected value projects the growth for the bond

    var wrappedValue: Int { .... }

    init(wrappedValue: Int = 0, minimumValue: Int, flexiInterest: Int, value: Int) { ... }
}

struct FoodBond {
    var bondName: String
    var value = BondValue(minimumValue: 0, flexiInterest: 0, value: 0) // Provide a default value

    init(bondName: String, minimumValue: Int, flexiInterest: Int, value: Int) {
        self.bondName = bondName
        self.value = BondValue(minimumValue: minimumValue, flexiInterest: flexiInterest, value: value)
    }
}

var foodBond = FoodBond(bondName: "Food Bond", minimumValue: 200, flexiInterest: 10, value: 200)
print("Initial bond current worth - \(foodBond.value.bondCurrentWorth)")
print("Bond growth - \(foodBond.value.projectedValue)")

Any suggestions will be really helpful.

like image 846
G.Abhisek Avatar asked Oct 31 '19 05:10

G.Abhisek


People also ask

How do you create a property wrapper in Swift?

To make our wrapper configurable, we need to add all configuration parameters through an initializer. If the initializer contains a wrappedValue attribute (the initial value of our property), it must be the first parameter.

What is a property wrapper Swift?

A property wrapper adds a layer of separation between code that manages how a property is stored and the code that defines a property. For example, if you have properties that provide thread-safety checks or store their underlying data in a database, you have to write that code on every property.

What is property Observer in Swift?

Property observers observe and respond to changes in a property's value. Property observers are called every time a property's value is set, even if the new value is the same as the property's current value .

What is published in SwiftUI?

@Published is one of the property wrappers in SwiftUI that allows us to trigger a view redraw whenever changes occur. You can use the wrapper combined with the ObservableObject protocol, but you can also use it within regular classes.


2 Answers

Referring to the section Memberwise Initialisers from Swift proposal doc for property wrappers:

Instance properties that have a property wrapper will have a corresponding parameter in the memberwise initializer, whose type will either be the original property type or the wrapper type, depending on the wrapper type and the initial value (if provided).

Solution:

struct FoodBond {
    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, value: value)
    }
}
like image 159
G.Abhisek Avatar answered Sep 27 '22 19:09

G.Abhisek


You can use the property wrapper without params and give it the type of the wrapped value, then create it in the init with your params:

struct FoodBond {
    var bondName: String

    @BondValue var bondValue : Int

    init(bondName: String, minimumValue: Int, flexiInterest: Int, value: Int) {
        self.bondName = bondName
        _bondValue = BondValue(minimumValue: minimumValue, flexiInterest: flexiInterest, value: value)
    }
}
like image 42
malhal Avatar answered Sep 27 '22 20:09

malhal