我是 ios 开发的新手,我想了解内存泄漏是如何在 swift
或 Objective-C
中发生的,谁能用小例子解释一下?
谢谢
最佳答案
小例子:
class A {
var b: B!
deinit {
print("deinit of A")
}
}
class B {
var a: A!
deinit {
print("deinit of B")
}
}
do {
let a = A()
let b = B()
a.b = b
b.a = a
}
如果您运行此代码(可能在 Playground 中),它不会打印任何内容。这意味着 deinit
从未调用过这两个对象,它们只是泄漏了。
但是,如果您将其中一个属性声明为 weak
:
class A {
weak var b: B!
deinit {
print("deinit of A")
}
}
然后 deinit
将被调用,您将在控制台中看到消息。
编辑:添加闭包示例
考虑这个例子:
class C {
var f: (Void -> Void)!
deinit {
print("deinit for C")
}
}
do {
let c = C()
c.f = {
print(c)
}
}
c
捕获 f
,f
捕获 c
。所以我们有内存泄漏。
要处理闭包中的泄漏,您有 2 个选择——声明捕获的对象是 weak
或 unowned
。像这样:
do {
let c = C()
c.f = { [weak c] in
print(c)
}
}
基本上,如果调用闭包时对象可能不存在并变为nil
,您将使用weak
;但如果您确定此时对象仍然存在,请改用 unowned
。
在我将 c
声明为闭包内的 weak
后,会打印“deinit for C”——这意味着一切都已成功解除分配。
这对开发者来说意味着什么?
几乎所有时候你都不必担心内存管理。它会自动为您完成。对象只在您需要时存在,在您不需要时消失。但是有 2 种非常常见的情况,您需要小心并考虑内存。
- 代表团。这是 Cocoa 中的常见模式,如果操作不当,可能会产生保留循环。始终将您的委托(delegate)声明为
weak
除非您有充分的理由不这样做。 - 关闭。闭包捕获周围范围内对象的引用并自动执行,恕不另行通知。实现闭包时,检查它是否会创建保留循环。如果是,请将问题变量声明为
weak
或unowned
。
有关更多信息,我建议您阅读官方的 Apple Swift 书籍,可以在 iBooks 或 here 中找到作为一个网站。
关于ios - swift 内存泄露怎么办?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36834935/