Last active
September 26, 2019 09:18
-
-
Save lamprosg/73249a4dc03c32a83c409e4fadb0eda4 to your computer and use it in GitHub Desktop.
(iOS) Property wrappers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| A property wrapper adds a layer of separation between code | |
| that manages how a property is stored and the code that defines a property | |
| */ | |
| //https://docs.swift.org/swift-book/LanguageGuide/Properties.html | |
| //To define a property wrapper, you make a structure, enumeration, or class that defines a wrappedValue property | |
| //wrappedValue can be anything, even generic value of the struct | |
| @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) | |
| } | |
| } | |
| //When you apply a wrapper to a property and you don’t specify an initial value | |
| //Swift uses the init() initializer to set up the wrapper. For example: | |
| struct ZeroRectangle { | |
| @SmallNumber var height: Int | |
| @SmallNumber var width: Int | |
| } | |
| var zeroRectangle = ZeroRectangle() | |
| print(zeroRectangle.height, zeroRectangle.width) | |
| // Prints "0 0" | |
| //----- | |
| //When you specify an initial value for the property | |
| //Swift uses the init(wrappedValue:) initializer to set up the wrapper | |
| //Example | |
| struct UnitRectangle { | |
| @SmallNumber var height: Int = 1 | |
| @SmallNumber var width: Int = 1 | |
| } | |
| var unitRectangle = UnitRectangle() | |
| print(unitRectangle.height, unitRectangle.width) | |
| // Prints "1 1" | |
| //----- | |
| //Otherwise use the specific initializer | |
| 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" | |
| //----- | |
| //you can also specify an initial value using assignment. | |
| //Swift treats the assignment like a wrappedValue argument and uses | |
| //the initializer that accepts the arguments you include. For example: | |
| 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" | |
| /*----------------------------------*/ | |
| //Projected values | |
| /* | |
| n addition to the wrapped value, a property wrapper can expose additional functionality | |
| by defining a projected value—for example, a property wrapper that manages access to a database | |
| can expose a flushDatabaseConnection() method on its projected value. | |
| The name of the projected value is the same as the wrapped value, except it begins with a dollar sign ($). | |
| */ | |
| @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" | |
| //Projected value can be of any type |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment