在Swift中,我们主要使用许多引用类,如
一个例子:
var slider:UISlider!
我的问题是我们是否必须将弱引用前缀引用为弱,以便ARC不会有强烈坚持,以便 ARC 可以在需要时删除它,或者只是创建一个强引用并在 viewDidUnload上将其强制为 nil deligate ??
示例:
slider = nil
我实际上不知道如何手动使用ARC 或手动处理ARC根本不需要?我不知道这个meamory处理
如果你碰到过这个并找到解决方案,请分享...
提前致谢....
答案 0 :(得分:2)
ARC {Automatic Reference Counting)
在Swift中的解释很好official documentation。
下面您可以找到ARC的4个重要方面的简单回顾。
ARC关联到类a retainCount
整数的每个实例。
此值表示对该特定实例的强引用数。
当此数字变为0时,将释放实例使用的内存。
class Something {}
var aVariable = Something()
// now the reference counting for this particular instance of Something is 1
现在我们的Something
实例已保存在内存中,因为其retainCount
值为1
。
var anotherVariable = aVariable
现在我们对2
的实例有Something
个强引用。好!它的retainCount
现在是2
,实例仍保留在内存中!
aVariable = nil
retainCount
刚刚成为1
。没问题,实例仍在内存中。
anotherVariable = nil
最后,我们实例的retainCount
变为0
。这意味着该实例已被释放,无法再访问。
Nope。事实上,当变量超出范围时,ARC会自动减少所引用实例的retainCount
。
在以下示例中,在}
retainCount
实例Something
之前,0
实例的func doSomethingUseful() {
let something = Something()
// ... do very important stuff here
}
减少并达到值nil
(并被释放)。
class Son {}
class Father {
var sons: [Son]
init (sons: [Son]) {
self.sons = sons
}
}
func lifeGoesOn() {
let son = Son()
// here the referenceCout of the instance of Son is 1
let father = Father(sons: [son])
// here the referenceCount of the instance of Son is 2...
// now variable son goes out of scope so the reatinCount of the instance of Son becomes 1
// also father goes out of scope, so the variable father.sons goes out of scope as well, so the `retainCount` of the instance of Son becomes 0
// and so both the instances of Father and Son gets freed
}
因此,在常见的情况下,您不需要将变量设置为retainCounts
,以强制ARC释放引用的实例。
另一个例子:
0
你可以看到这就像多米诺骨牌效应。释放实例时,将删除对其他实例的所有引用。因此,引用实例的class Son {
let father:Father
init(father:Father) {
self.father = father
}
}
class Father {
var sons: [Son]
init (sons: [Son]) {
self.sons = sons
}
}
会减少。如果成为father
,他们就会被释放。等等...
好的,如果我有2个课程,会发生什么?
son
让我们现在创建从son
到father
的引用,反之亦然从func lifeGoesOn() {
var father = Father(sons:[])
// retainCount of the instance of Father is 1
var son = Son(father: father)
// retainCount of the instance of Father is 2
// retainCount of the instance of Son is 1
father.sons.append(son)
// retainCount of the instance of Father is 2
// retainCount of the instance of Son is 2
// Now we have a problem
}
到retainCount
。
Father
在函数中,父变量超出范围,因此1
实例的son
变为retainCount
。
同样,变量Son
超出范围,1
实例的Son
变为Father
。
这里的问题是Father
的实例引用了Son
的实例(将此实例保留在活动内存中)。 class Son {
weak var father:Father?
init(father:Father) {
self.father = father
}
}
的实例引用了Son
的实例。这两个实例不应再存在于内存中。程序员无法访问它们,因为引用它们的所有变量都消失了。
这是一个问题。
构建代码时,应注意强保留周期。让我们来重构我们的代码来解决这个问题。
Father
现在,从weak
到UIViewController
的引用为MyCustomViewController
。这意味着当ARC计算实例的(强)引用数时,它不计算在内。这解决了上一段中看到的问题。
我希望这个主题现在更加清晰。我没有涉及几种情况。再次,官方文档非常好,详尽无遗。
如果您有自定义class MyCustomViewController : UIViewController {
var something = Something()
}
class Something {
init() { // called when memory is allocated
debugPrintln("The instance of Something has been created")
}
deinit { // called when memory is freed
debugPrintln("The instance of Something has been freed")
}
}
(我们称之为MyCustomViewController
),并且此类具有对象的强大属性,请查看发生的情况。
MyCustomViewController
当您展示Something
时,会创建MyCustomViewController
的实例。然后还会创建UINavigationController
的实例。
现在retaintCount = 1
引用了Something
的实例,因此MyCustomViewController
已retainCount = 1
。
同样,UINavigationController
的实例引用了MyCustomViewController
的实例,因此它具有MyCustomViewController
。
因此Something
的实例保持活跃 MyCustomViewController
的实例。 UINavigationController
的实例保持活跃 MyCustomViewController
的实例。
UINavigationController - (强) - > MyCustomViewController - (强) - > 东西
接下来你决定解雇retainCount
,因此iOS会将其设置为动画以离开屏幕。如果它不再可见,则会将MyCustomViewController
实例中的引用移除到实例MyCustomViewController
。
UINavigationController - (REMOVED) - MyCustomViewController - (强) - > 东西
这意味着retainCount
实例的Something
变为0,因为:现在没有人引用它!
因此init
的实例将从内存中删除。在这个过程中,它的属性是无效的。
UINavigationController - (删除) - [免费记忆] - (删除) - 东西
现在deinit
实例的Something
已变为0。
所以它也将从内存中删除。
UINavigationController - (REMOVED) - [free memory] - (REMOVED) - > [免费记忆]
最后,我覆盖了{{1}}的{{1}}和{{1}}方法,以便您可以跟踪相关实例的分配和释放。查看日志(或使用断点),您可以验证我在这里说的内容。
希望这有帮助。
答案 1 :(得分:0)
如果您正在讨论由视图本身初始化的视图控制器属性(例如UILabel
或几乎所有您在IB中定义的UIView
的子类),Xcode会将它们指定为{ {1}}自动,因为视图(而非视图控制器)已创建强引用。
大多数情况下,您不需要手动将weak
添加到您的媒体资源中,除非您在代码中的其他位置定义了强关系(这是您拥有代理时的典型情况)。
答案 2 :(得分:0)
当你有自己开发的具有双向参考的不同课程时,你只需要考虑它。 (Apple's example中的公寓类和人员类。)