值类型

作者: 幸运者_Lucky | 来源:发表于2022-03-04 17:26 被阅读0次
    struct A {
        var a = 10
    }
    
    struct B {
        var a = A() {
            didSet {
                print(1, a.a)
            }
        }
        
        var aa = A() {
            didSet {
                print(11, aa.a)
            }
        }
        
        mutating func set(a: Int) {
            self.a.a = a
            set(aa: a)
        }
        
        mutating func set(aa: Int) {
            self.aa.a = aa
        }
    }
    
    struct C {
        var b = B() {
            didSet {
                print("didSet")
            }
        }
        
        mutating func set(a: Int) {
            b.set(a: a)
        }
    }
    
    var c = C()
    c.set(a: 11)
    
    // 打印顺序
    // 1 11
    // 11 11
    // didSet
    

    看这段代码,理解值类型的实现。

    struct Thing {
        var property: Int = 0
    }
    
    var optionalThing: Thing? {
        didSet { print("didSet") }
    }
    
    optionalThing?.property = 1
    // 打印
    // didSet
    
    struct A { 
        var foo: Int { 
            didSet { print("fooDidSet") } // not called
        }
    }
    
    var a: A? {
        didSet { print("didSet") } // called
    }
    
    a?.foo = 5
    

    看上面两段代码,理解可选链断开的时机,也可能是 Swift 的 Bug。

    值类型 malloc: Double free of object

    class SS {}
    struct Store {
        var a = 0
        var k = SS()
    }
    
    func test() {
        var store = Store()
        DispatchQueue.concurrentPerform(iterations: 1_000_000) { i in
            store = Store()
        }
    }
    

    上面这段代码,会报 malloc: Double free of object 0x1007d22a0,当把 SS 改成 struct,就不会挂掉。值类型在存在堆内存维护的情况下,会出现对引用类型的重复释放问题。wwdc

    String 关于触发引用类型

    func test() {
        var store = ""
        DispatchQueue.concurrentPerform(iterations: 1_000_000) { i in
            store = "\(1111):\(1111):\(1111):\(1111)"
        }
    }
    

    当 store = "(1111):(1111):(1111)" 的时候不会挂掉,但当是上面的代码就会挂掉,触发发了引用类型。

    func test() {
        var store = ""
        DispatchQueue.concurrentPerform(iterations: 1_000_000) { i in
            store = "alsdfjlakjsdfaklsjdflakjsdfolakjsdflkajsdfklajsdlkfjasldkfja"
        }
    }
    

    上面这段代码没挂掉,因为字符串常量存放在固定的常量区。

    综上,Swift String Key 的使用,尽量使用无引用类型 struct 来代替,因为不会触发引用类型。

    Property observers being called on a nil struct instance upon attempt to mutate a member property
    Bug or intended? “thing?.property = something” will trigger didSet observer even if thing is nil, but ONLY IF thing is a struct type

    https://forums.swift.org/t/understanding-swifts-value-type-thread-safety/41406

    相关文章

      网友评论

          本文标题:值类型

          本文链接:https://www.haomeiwen.com/subject/heizaltx.html