【问题标题】:Setting elements in NSMutableArray to nil将 NSMutableArray 中的元素设置为 nil
【发布时间】:2013-07-16 02:43:04
【问题描述】:

我有一个 NSMutableArray,其中包含我创建并分配内存的一大堆 UITextField。

在我的 viewDidUnload 方法中,我需要释放这个内存。我该怎么做?

for(int i = 0; i < [arr count]; i++){
    UITextField* txtField = [arr objectAtIndex i];
    txtField = nil;
}
arr = nil;

这行得通吗?还是我只需要设置 arr = nil;?

我正在使用 ARC,所以我设置为 nil 不释放。

【问题讨论】:

    标签: objective-c memory-management automatic-ref-counting


    【解决方案1】:

    如果数组是视图控制器的实例变量,只要您使用 ARC,它就会在视图控制器离开内存时自动释放。

    如果需要手动移除数组,设置为nil。

    arr = nil;
    

    如果以后需要重用数组,则需要在设置为nil后重新分配。

    假设你的数组是你对象的@property,一个好的技巧是在getter中分配数组:

    -(NSMutableArray*)arr {
        if (!_arr) {
            _arr = [[NSMutableArray alloc] init];
        }
        return _arr;
    }
    

    这样,当你尝试访问它时,你总是会得到一个数组,即使它以前被设置为 nil。

    【讨论】:

    • arr 是 viewController 的一个属性。所以我不需要 =nil 我在 arc 中分配的任何东西?一旦控制器离开内存,它们就会自动被释放,所以当我更改视图控制器时?
    • 正确,这是 ARC 的一大优势。过去,您必须释放和释放对象。现在它已经为你完成了。
    • 太棒了。感谢您的帮助。
    • btw - 如果您通过导航更改视图控制器,您的 VC 只会在“返回”导航期间从内存中删除。向前导航让您的 VC 留在记忆中。
    • 说我要这样做:[self presentModalViewController:view animated:true];那会从内存中释放控制器吗?或者我将如何从内存中释放它?
    【解决方案2】:

    让我们看看你的代码做了什么来了解发生了什么:

    UITextField* txtField = [arr objectAtIndex i];
    

    对数组中的值进行复制NSMutableArray 中的值是引用,并将该值存储在变量txtField 中。正如txtField 被隐含地定义为持有强引用,ARC 将(根据任何优化)在引用中注册所有权权益(又名“保留”)。你的下一行:

    txtField = nil;
    

    将 nil 引用值存储在 txtField 中。由于txtField 持有强引用,因此任何存储都会导致 ARC 放弃对存储在变量中的先前引用值的所有权权益(也称为“释放”)。

    数组永远不会改变。你已经迭代了它的内容,复制了每个值,保留了那个值,释放了那个值。最后你写:

    arr = nil;
    

    将 nil 引用值存储在 arr 中。由于arr 持有强引用,因此任何存储都会导致ARC 放弃对存储在变量中的先前参考值的所有权权益(也称为“释放”)——而先前的值是您对NSMutableArray 的引用。如果该数组没有其他所有者,则该数组将被销毁,并且当数组被销毁时,它将放弃其对其包含的任何值的所有权——在本例中为您的 UITextField 实例,如果没有其他所有者,则他们被摧毁了......

    所以你最多只需要:

    arr = nil
    

    但您甚至可能不需要它。由于arr 在其生命周期结束时持有强引用 - 如果是局部变量,则在包含其声明的块或方法的末尾,或者如果实例变量,则当实例被销毁时 - 然后 ARC 将放弃其所有权权益,等等。 .

    HTH

    【讨论】:

    • 好的。这就说得通了。感谢您的帮助。
    【解决方案3】:

    使用 ARC 时,您可以通过将变量设置为 nil 来释放变量,就像使用 arr = nil 所做的一样。请注意,只有当所有指向对象的指针都设置为 nil 时才会释放内存,因此请确保您没有在其他任何地方持有它们。

    其次,如果您遇到内存问题,您应该在 didReceiveMemoryWarning 方法中处理此问题,因为 iOS 6 不再支持 viewDidUnload。

    【讨论】:

    • 好的。所以从 ios 6 开始,我使用 didReceiveMemoryWarning 来释放任何东西而不是 viewDidUnload?
    • 正如上面的 jb_OH 所说,当视图控制器从导航堆栈中弹出时,视图控制器的所有属性都将被释放。如果您遇到内存不足错误,您只需要手动释放内容。如果内存不足,则应在 didReceiveMemoryWarning 中处理释放对象。您可以在 iOS 5 和 6 上执行此操作,我建议您这样做以保持一致性。
    猜你喜欢
    • 2019-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多