update: 动态库、静态库的编译链接细节

This commit is contained in:
FantasticLBP
2025-06-23 01:18:55 +08:00
parent aca020701b
commit 1142064d28
129 changed files with 10932 additions and 2615 deletions

View File

@@ -1,6 +1,188 @@
# 内存管理
## 弱引用
Swift 和 OC 都是通过引用计数方式来管理内存的。
Swift 的 ARC 存在3种情况
- 强引用strong reference。默认情况下都是强引用。
当一个强指针离开作用域后,会自动释放对象,调用 deinit 方法。
```swift
class Person {
deinit {
print("Person deinit")
}
}
func test () {
let p: Person = Person()
}
print("1")
test()
print("2")
// console
1
Person deinit
2
```
- 弱引用weak reference。通过 weak 定义弱引用。**必须是可选类型因为实例销毁后ARC 会自动将弱引用设置为 nil**。
```swift
weak var p: Person? = Person()
```
- 弱引用如果被设置为 nil是不会触发属性观察器的 willSet、didSet 方法的
```swift
class Dog {
deinit {
print("Dog deinit")
}
}
class Person {
weak var dog: Dog? {
willSet {
print("willSet")
}
didSet {
print("didSet")
}
}
deinit {
print("Person deinit")
}
}
func test () {
let p: Person = Person()
p.dog = Dog()
print(p)
}
print("1")
test()
print("2")
// console
1
willSet // 这里的触发是 test 方法里,给 person 对象设置了 dog 属性时触发的。但是 weak 指针设置为 nil 的时候没有触发属性观察器
didSet
Dog deinit
SwiftDemo.Person
Person deinit
2
```
换一种写法。可以发现在 init 方法里面,属性观察器 willSet、didSet 是不会触发的。
```swift
class Dog {
deinit {
print("Dog deinit")
}
}
class Person {
weak var dog: Dog? {
willSet {
print("willSet")
}
didSet {
print("didSet")
}
}
init (dog: Dog?) {
self.dog = dog
}
deinit {
print("Person deinit")
}
}
func test () {
let p: Person = Person(dog: Dog())
print(p)
}
print("1")
test()
print("2")
// console
1
Dog deinit
SwiftDemo.Person
Person deinit
2
```
- 无主引用unowned reference。通过 unowned 定义无主引用
- 不会产生强引用,非可选类型。实例销毁后仍然存储着实例的内存地址,类似 OC 的 `unsafe_retained`
- 如果在实例销毁后访问无主引用,会产生野指针错误
weak、unowned 只能用在类实例上。比如:
```swift
protocol Liveavle: AnyObject { }
class Person { }
weak var p1: Person?
weak var p2: AnyObject?
weak var p3: Liveavle?
unowned var p4: Person?
unowned var p5: AnyObject?
unowned var p6: Liveavle?
```
## 循环引用
weak、unowned 都能解决循环引用问题。但是 weak 由于当对象释放后,会把指针设置为 nil。所以 unowned 会比 weak 的性能更好。
- 在生命周期中对象可能会变为 nil推荐使用 weak
- 初始化赋值后再也不会变为 nil 的对象,推荐使用 unowned
## 闭包的循环引用
<img src="./../assets/SwiftBlockRetainCycle.png" style="zoom:40%">
上面的代码会发生循环引用,会导致局部变量的 p 无法释放(看不到 Person 的 deinit 方法调用)
解法:
- **在闭包表达式的捕获列表声明 weak 或者 unowned 引用,解决循环引用的问题**
因为在闭包里,声明的捕获列表中将 p 用 weak 修饰,所以可以为 nil。p 使用到的地方必须用 `p?.run()`
```swift
class Person {
var fn:(() -> ())?
func run () { print("run") }
deinit { print("deinit") }
}
func test () {
let p = Person()
p.fn = {
[weak p] in
p?.run()
}
}
test()
// deinit
```
另一种写法
```swift
p.fn = {
[unowned p] in
p.run()
}
```
-
```swift
class Person {
lazy var fn:() -> () = {
self.run()
}
func run () { print("run") }
deinit { print("deinit") }
}
```
## @escaping
@@ -169,7 +351,7 @@ print(age)
- `changeValue1` 的参数是不可变的指针,所以方法内部去修改值,编译器会报错
- `changeValue2` 的参数是可变的指针,所以方法内部去修改值,编译没问题
- 指针加了型,访问真实的值可以通过 `指针.pointee` 去访问
- 指针加了型,访问真实的值可以通过 `指针.pointee` 去访问