Properties
Computed properties are provided by classes, structures, and enumerations.
Stored properties are provided only by classes and structures.
Stored Properties
Stored Properties of Constant Structure Instances
struct FixedLengthRange {
var firstValue: Int
let length: Int
}
let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)
// this range represents integer values 0, 1, 2, and 3
rangeOfFourItems.firstValue = 6
// this will report an error, even though firstValue is a variable property
If the final type of an instance of Structure is constant, just like the example above, we cannot change the inner property even if it’s variable.
Due to the structure is value types.
So for Class which is refrence types, it is not same, we can change the inner value even if it is assign a constant value.
Lazy Stored Properties
We all know how to create a lazy property, but I I will highlight you this at here:
==If a property marked with the lazy
modifier is accessed by multiple threads simultaneously and the property hasn’t yet been initialized, there’s no guarantee that the property will be initialized only once.==
Property Wrappers
It is the charecataristic I never heard, so it is amazing for me.
@propertyWrapper
struct TwelveOrLess {
private var number = 0
var wrappedValue: Int {
get { return number }
set { number = min(newValue, 12) }
}
}
We can use the @propertyWrapper
keyword to define a Struct
and use wrappedValue
to make a rule, just like the example above.
Then,
struct SmallRectangle {
@TwelveOrLess var height: Int
@TwelveOrLess var width: Int
}
var rectangle = SmallRectangle()
print(rectangle.height)
// Prints "0"
rectangle.height = 10
print(rectangle.height)
// Prints "10"
rectangle.height = 24
print(rectangle.height)
// Prints "12"
we can use this struct to define a property, and this property has to comply this rule, just like the example above.
The height and width cannot beyond 12.
Setting Initial Values for Wrapped Properties
@propertyWrapper
struct SmallNumber {
private var maximum: Int
private var number: Int
var wrappedValue: Int {
get { return number }
set { number = min(newValue, maximum) }
}
init() {
maximum = 12
number = 0
}
init(wrappedValue: Int) {
maximum = 12
number = min(wrappedValue, maximum)
}
init(wrappedValue: Int, maximum: Int) {
self.maximum = maximum
number = min(wrappedValue, maximum)
}
}
We can see the example above, there are 3 initializer in SmallNumber
, and we can make the default value on each one.
and use it like below:
struct ZeroRectangle {
@SmallNumber var height: Int
@SmallNumber var width: Int
}
var zeroRectangle = ZeroRectangle()
print(zeroRectangle.height, zeroRectangle.width)
// Prints "0 0"
struct UnitRectangle {
@SmallNumber var height: Int = 1
@SmallNumber var width: Int = 1
}
var unitRectangle = UnitRectangle()
print(unitRectangle.height, unitRectangle.width)
struct NarrowRectangle {
@SmallNumber(wrappedValue: 2, maximum: 5) var height: Int
@SmallNumber(wrappedValue: 3, maximum: 4) var width: Int
}
var narrowRectangle = NarrowRectangle()
print(narrowRectangle.height, narrowRectangle.width)
// Prints "2 3"
narrowRectangle.height = 100
narrowRectangle.width = 100
print(narrowRectangle.height, narrowRectangle.width)
// Prints "5 4"
struct MixedRectangle {
@SmallNumber var height: Int = 1
@SmallNumber(maximum: 9) var width: Int = 2
}
var mixedRectangle = MixedRectangle()
print(mixedRectangle.height)
// Prints "1"
mixedRectangle.height = 20
print(mixedRectangle.height)
// Prints "12"
Especially the last example above, we can just fill apartful values of initializer which can aim autoly.
Projecting a Value From a Property Wrapper
In addition to wrappedValue
, projectedValue
which can be any type to store a explicit value assioated others is another keyword in Property Wrapper.
And we can access the ProjectedValue via $
.
@propertyWrapper
struct SmallNumber {
private var number = 0
var projectedValue = false
var wrappedValue: Int {
get { return number }
set {
if newValue > 12 {
number = 12
projectedValue = true
} else {
number = newValue
projectedValue = false
}
}
}
}
struct SomeStructure {
@SmallNumber var someNumber: Int
}
var someStructure = SomeStructure()
someStructure.someNumber = 4
print(someStructure.$someNumber)
// Prints "false"
someStructure.someNumber = 55
print(someStructure.$someNumber)
// Prints "true"
Let’s think!