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 inThe initializerSet an initial value for the storage property
  • canAssign a default property valueAs 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