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
网友评论