Instance-related attributes in Swift fall into two broad categories
Stored Property
- Similar to the concept of a member variable
- Stored in the instance’s memory
- Structures and classes can define storage properties
- Enumerations cannot define storage properties
Computed Properties (Computed Property)
- The essence is method (function)
- Does not occupy the memory of the instance
- Enumerations, structures, and classes can all define computed properties
Struct diameter: struct diameter: struct diameter: struct diameter: Double { set { radius = newValue / 2 } get { radius * 2 } } }Copy the code
# Store attributes
Swift has a clear rule about storage properties
When creating an instance of a class or structure, you must set an appropriate initial value for all storage properties
- Can be found in
The initializer
Set an initial value for the storage property- can
Assign a default property value
As part of the property definition
Struct Point {var x: Int var y: Int} var p1 = Point() var p2 = Point(x: 10, y: 10) Struct Point {var x: Int var y: struct Point {var x: Int var y: Int init() {x = 10 y = 10}} var p1 = Point() Int = 10 var y: Int = 10 } var p1 = Point()Copy the code
# count attributes
The newValue passed in by set is called newValue by default and can be customized
struct Cirle { var radius : Double var diameter : NewDiameter set(newDiameter) {radius = newDiameter / 2} get {radius * 2}}}Copy the code
Read-only computing properties: Only GET, no set
struct Cirle { var radius : Double var diameter : Get {radius * 2}}} var c = Cirle(radius: Parsed diameter: struct Cirle {var radius: parsed diameter: struct Cirle {var radius: parsed diameter: struct Cirle {var radius: parsed diameter: struct Cirle {var radius: parsed diameter: struct Cirle {var radius: parsed diameter: struct Cirle {var radius: parsed diameter: Var diameter: Double {radius * 2}}Copy the code
You can only define computed properties using var, not let
Let stands for constant: The value is immutable and the value of a computed property can change (even if it is a read-only computed property)
# rawValue principle for enumeration
The essence of enumerating a raw rawValue is that it is a read-only computed property
enum TestEnum : Int {
case test1 = 1, test2 = 2, test3 = 3
var rawValue : Int {
get {
switch self {
case .test1:
return 10
case .test2:
return 11
case .test3:
return 12
}
}
}
}
Copy the code
Lazy Stored Property
Using lazy, you can define a lazy storage property that is initialized only when the property is first used
The lazy attribute must be var, not let, which must have a value before the instance’s initialization method completes
If multiple threads access the lazy property for the first time (not thread-safe)
There is no guarantee that a property will be initialized only once
class Car { init() { print("Car init") } func run() { print("Car is running") } } class Person { lazy var car = Car() Init () {print (" Person "init)} func goOut () {car. The run ()}} var p = Person () print (" -- -- -- -- -- -- -- -- --") p.g oOut () ` output ` Person init ---------- Car init Car is runningCopy the code
Note: When a structure contains a deferred storage property, only var can access the deferred property
This is because delayed initialization requires a change in the structure’s memory
Struct Point {var x = 0 var y = 0 lazy var z = 0} let p = Point()Copy the code
Property Observer
You can set a property observer for a non-lazy var storage property. Setting a property value in an initializer does not trigger willSet and didSet. Setting an initial value when a property is defined does not trigger willSet and didSet
Struct Circle {/// Double {/// Set willSet {print("will Set ", NewValue)} /// Modified callback didSet {print("did Set ",oldValue,radius)}} init() {/// Assign the storage property in the initializer /// do not trigger the property observer (will Set) Radius = 1.0 print("Circle init!" )}} /// Circle init var Circle = Circle() // did Set 1.0 10.5 Circle print(circle.radius)Copy the code
Global variable, local variable
Attribute observer and attribute calculation functions can also be applied to global and local variables
func test() {
var age = 10 {
willSet {
print("will set",newValue)
}
didSet {
print("did set",oldValue,age)
}
}
age = 11
/// will set 11
/// did set 10 11
}
test()
Copy the code
#inout
If the argument has a physical memory address and no property viewer is set
Pass the memory address of the argument directly to the function (the argument is passed by reference)
If the argument is a evaluated property or a property observer is set
(2) Pass the memory address of the Copy into the function (Copy is passed by reference). Inside the function, you can change the value of the Copy. (3) After the function returns, the value of the Copy overwrites the value of the argument.
Summary: The essence of Inout is reference passing.
# Type Property
Strictly speaking, attributes can be divided into
Instance Property: Stored Instance properties can only be accessed through instances: They are Stored in Instance memory, and each Instance has one Computed Instance Property.
Type Property: Can only be accessed by Type
Stored Type Property: During the entire run of a program, only one memory (similar to global variables) is used to calculate Type properties.
You can define type attributes through static
If it is a class, the keyword class can also be used
struct Car { static var count: Int = 0 init() {car.count += 1}} let c1 = Car() let c2 = Car() let c3 = Car()Copy the code
Unlike store instance properties, you do not have to set initial values for store type properties
Because type properties don’t have an init initializer to initialize storage properties like instances do
The storage type attribute is lazy by default and is initialized the first time it is used
It is guaranteed to be initialized only once, even if accessed by multiple threads at the same time
The storage type attribute can be let
Enumerated types can also define type properties (storage type properties, computed type properties)
Example: Create a singleton object class FileManager {/// is thread-safe (because the type attribute is static) public static let share = FileManager() // private Private init() {} func open() -> () {print(" open ")} func close() -> () {print(" close ")}} FileManager.share.open() FileManager.share.close()Copy the code