attribute

  • Storage properties
    • 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
    • When creating a class or structure, you must set an appropriate initial value for all storage properties
  • Calculate attribute
    • The essence is the method (function)
    • Does not take up the memory of the instance (just like normal methods do not take up memory)
    • Structures, classes, and enumerations can define storage properties
    • Read-only compute property, only get, no set
    • You can only define computed properties using var, not let, because even read-only properties can change in value
  • Deferred storage property
    • Using lazy, you can define a lazy storage property that is initialized only when the property is first used
    • When a structure contains a deferred storage property, only var can access the deferred storage property because the structure’s memory needs to be changed when the deferred property is initialized
Struct diameter: Double; struct diameter: Double {set{radius = newValue / 2} get {radius * 2 // herereturn}}} can be omittedCopy the code

There is also a byte to store whether the lazy attribute is initialized. If the lazy attribute is not initialized, the print result should be 24, 24, 8

struct Point {
    var x = 10
    var y = 11
    lazy var z = 12
}

var point = Point()
printMemory(t1: point)
point.z = 10
printThe Memory (t1: point) -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the execution result -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- (LLDB) p point (swiftstudy. Point)$R0 = {
  x = 10
  y = 11
  $__lazy_storage_$_z = nil
}
(lldb) x/5wg 0x7ffeefbff410
0x7ffeefbff410: 0x000000000000000a 0x000000000000000b
0x7ffeefbff420: 0x0000000000000000 0x0000000000000001
0x7ffeefbff430: 0x0000000000000000
(lldb) c
Process 26808 resuming
25
32
8
(lldb) x/5wg 0x7ffeefbff410
0x7ffeefbff410: 0x000000000000000a 0x000000000000000b
0x7ffeefbff420: 0x000000000000000a 0x0000000000000000
0x7ffeefbff430: 0x0000000000000000
Copy the code

Consider: is it the same as usual if it is a class?

Lazy is wrapped as $__lazy_storage_$_z.Copy the code
class Point {
    var x = 10
    var y = 11
    lazy var z = 12
}

let point = Point()
printHeap(p: point)
point.z = 10
printHeap (p: point) -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - the execution result -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- (LLDB) p point (swiftstudy. Point)$R0 = 0x000000010121ede0 {
  x = 10
  y = 11
  $__lazy_storage_$_z = nil
}
(lldb) x/10wg 0x000000010121ede0
0x10121ede0: 0x000000010000ba28 0x0000000200000002
0x10121edf0: 0x000000000000000a 0x000000000000000b
0x10121ee00: 0x0000000000000000 0x0000000000000001
0x10121ee10: 0x0000000000000000 0x0000000000000000
0x10121ee20: 0x00007fff77fd3080 0x00000000e3aa30a7
48
48
(lldb) x/10wg 0x000000010121ede0
0x10121ede0: 0x000000010000ba28 0x0000000200000002
0x10121edf0: 0x000000000000000a 0x000000000000000b
0x10121ee00: 0x000000000000000a 0x0000000000000000
Copy the code

Attribute viewer

  • You can set property observers for non-lazy VAR storage properties
  • It’s like observer mode
  • Can be used for local and global variables
struct Circle {
    var radius: Double = 10 {
        willSet {
            print("willSet", newValue)
        }
        didSet {
            print("didSet", oldValue, radius)
        }
    }
}

let c = Circle()
c.radius = 10
Copy the code

Summary of inout essence

  • 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
    • The Copy In Copy Out policy is adopted
      • When this function is called, the value of the argument is copied to produce a copy.
      • The memory address of the copy is passed to the function (the copy is passed by reference), and the value of the copy can be modified inside the function
      • After the function returns, the value of the copy overwrites the value of the argument.
  • Summary: The essence of Inout is reference passing.

The type attribute

  • Instance properties: Can only be accessed by instance
    • Storage instance properties: Stored in the memory of the instance, each instance has one copy
    • Compute instance attributes:
  • Type attributes: Can only be accessed by type
    • Storage type attributes: the entire program runs, only 1 memory (similar to global variables), can be regarded as a global variable (because its memory and global variables are next to each other), just add a limited scope, is to define his structure, class and so on
    • Evaluate type attributes
    • Unlike store instance properties, you must set initial values for store type properties
      • Because types don’t have an init initializer like instances do to initialize storage properties
    • The default storage type attribute is lazy, which is initialized only when used for the first time, even if accessed by multiple threads at the same time. It can also be a let
      • Why is thread safety guaranteed? This is because swift_once is called at the bottom, which is dispatch_once from GCD
      • Static globalizes the memory to which the pointer points. Static globalizes the memory to which the pointer points
  • You can define type attributes through static
    • The class keyword can also be used for classes. If you define a class property as static, subclasses cannot inherit that property