【问题标题】:NSMutableArray object ownershipNSMutableArray 对象所有权
【发布时间】:2014-06-09 00:20:25
【问题描述】:

我在 TableViewController 中有 NSMutableArray 来保存项目,这些项目显示在 TableView 中。 NSMutableArray 正在 viewDidLoad 方法中填充。

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self populateItems];
}
- (void)populateItems {
    for (int i = 0; i < numberOfItems; i++) {
        Item *item = [Item createItem];
        [self.items addObject:item];
        item = nil;   // to ensure that newly created object is not pointed by item and only owned by NSMutableArray
    }
}

现在是在索引之间移动行的方法

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
    Item *item = [self.items objectAtIndex:fromIndexPath.row];

    [self.items removeObjectAtIndex:fromIndexPath.row];

    [self.items insertObject:item atIndex:toIndexPath.row];

    [self.tableView reloadData];
}

在这种方法中,我从 NSMutableArray 中获取对象并从 NSMutableArray 中删除该对象,然后再将其插入数组中。

我的问题是—— 如果 NSMutable 是其中对象的唯一所有者 然后从数组中删除它后,应该没有人指向项目对象。 因此它应该被释放,但事实并非如此。它再次成功插入到 tableview 中。为什么它没有发生。

我相信行 Item *item = [self.items objectAtIndex:fromIndexPath.row]; 项目指针不是 fromIndexPath 处存在的对象的所有者

【问题讨论】:

    标签: ios objective-c nsmutablearray uitableview


    【解决方案1】:

    以下行声明了对该对象的强引用。

    Item *item = [self.items objectAtIndex:fromIndexPath.row];
    

    这允许您将其从数组中删除并再次插入。

    如果出于某种原因您不希望 item 成为强参考,您可以这样做:

    _weak Item *item = [self.items objectAtIndex:fromIndexPath.row];
    

    【讨论】:

    • 成功了。通过将 __weak 添加到 Item 对象进行检查,应用程序崩溃说我们无法添加 nil 对象,这是因为我们从数组中删除了 item 已将 item 设置为 nil
    【解决方案2】:

    假设您启用了 ARC,并且您应该启用 ARC,这行代码:

    Item *item = [self.items objectAtIndex:fromIndexPath.row];
    

    会默默地为您保留该对象,直到它不再使用为止。

    如果您禁用了 ARC,则有以下三种可能性:

    1) 数组以外的其他东西保留了对象,这可能是内存泄漏,您应该进一步调查。

    2) 对象已被释放,但该内存位置尚未覆盖任何内容,因此它仍然可以正常工作。呸!这就是 ARC 旨在解决的问题类型。

    3) Apple 可能不会在从数组中删除对象后立即释放该对象,这可能是出于性能原因。为了提高性能和电池寿命,Apple 采取了大量未记录且通常很奇怪的内存管理行为,尤其是在他们控制 CPU 硬件且不必担心向后兼容性的 iOS 上。

    总而言之,如果您还没有启用 ARC,您应该启用 ARC。而且您不能依赖被“破坏”的对象。苹果实际上并没有保证当你从数组中删除一个对象时它会被销毁,他们只是告诉开发人员他们的代码必须假设它可能已经被销毁了。

    【讨论】:

      【解决方案3】:

      你有一个局部变量item。默认情况下,变量是强的。所以item 是一个强变量。只要该变量存在,它就会拥有保存到它的对象的所有权。

      局部变量仅在其作用域存在时才存在。在这段代码中:

      -(void) someMethod
      {
        NSMutableArray *array1 = [NSMutableArray new];
        {
          NSMutableArray *array2 = [NSMutableArray new];
          [array2 addObject: @"Foo"];
          [array1 addObject: @"Bar"];
        }
        //At this point, array2 no longer exists, so the string "Foo" is deallocated"
      
        //array1 is still in scope, so the string "bar" still exists
        __weak NSMutableArray *array3;
      
        //The line below is useless since the array is released as soon as it is created
        array3 = [NSMutableArray new];  
      }
      

      NSMutableArray array1 存在于方法的生命周期,因为它的局部变量是强的(默认)。

      变量 array2 也很强大,但它的范围是包围它的大括号。一旦到达右大括号,代码就会退出该范围,因此该变量不再为任何人所有,并被释放。

      这有帮助吗?

      【讨论】:

        猜你喜欢
        • 2014-04-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多