如何使用自动引用计数(ARC)?

时间:2015-07-10 17:06:42

标签: ios swift memory-management memory-leaks automatic-ref-counting

在Swift中,我们主要使用许多引用类,如

  1. 的UITableView
  2. UIStepper
  3. 的UILabel
  4. 的NSTimer
  5. UISlider等..
  6. 一个例子:

      

    var slider:UISlider!

    我的问题是我们是否必须将引用前缀引用为,以便ARC不会有强烈坚持,以便 ARC 可以在需要时删除它,或者只是创建一个强引用并在 viewDidUnload上将其强制为 nil deligate ??

    示例:

      

    slider = nil

    我实际上知道如何手动使用ARC 或手动处理ARC根本不需要?我不知道这个meamory处理

    如果你碰到过这个并找到解决方案,请分享...

    提前致谢....

3 个答案:

答案 0 :(得分:2)

ARC {Automatic Reference Counting)在Swift中的解释很好official documentation

下面您可以找到ARC的4个重要方面的简单回顾。

1。基本

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。这意味着该实例已被释放,无法再访问。

2。当你完成变量时,你应该设置为nil?

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,他们就会被释放。等等...

第3。保留周期

好的,如果我有2个课程,会发生什么?

son

让我们现在创建从sonfather的引用,反之亦然从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的实例。这两个实例不应再存在于内存中。程序员无法访问它们,因为引用它们的所有变量都消失了。

这是一个问题。

4。参考文献

构建代码时,应注意强保留周期。让我们来重构我们的代码来解决这个问题。

Father

现在,从weakUIViewController的引用为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的实例,因此MyCustomViewControllerretainCount = 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)

ARC主要是正常工作。在使用Cocoa类(例如您列出的类)时,通常不必担心声明弱。

当你有自己开发的具有双向参考的不同课程时,你只需要考虑它。 (Apple's example中的公寓类和人员类。)