简体   繁体   中英

NSMutableArray object ownership

I have NSMutableArray in a TableViewController to hold the items, which are shown in TableView. NSMutableArray is being populated in viewDidLoad Method.

- (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
    }
}

Now in method to move rows between indexes

- (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];
}

In this method I am getting the object from NSMutableArray and removing that object from NSMutableArray before inserting it into array again.

My questions are - If NSMutable was sole owner of the objects in it Then after removing it from array, nobody should have been pointing to the item object. Hence it should have been released but it is not so. It is successfully being inserted in the tableview again. Why it is not happening so.

I believe in line Item *item = [self.items objectAtIndex:fromIndexPath.row]; item pointer is not being owner of the object present at fromIndexPath

The following line declares a strong reference to the object.

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

This allows you to remove it from the array and insert it again.

If for some reason you wanted item to not be a strong reference you could do this:

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

Assuming you have ARC enabled, and you should have ARC enabled, this line of code:

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

Will silently retain the object for you, until it passes out of use.

If you've got ARC disabled, then there are three possibilities:

1) Something else other than the array is retaining the object, which might be a memory leak and you should investigate further.

2) The object has been released, but nothing has been overwritten at that memory location yet so it still works perfectly. Yuck! This is the type of problem ARC is intended to solve.

3) Apple might not immediately release the object after it has been removed from the array, which would probably be for performance reasons. There is a ton of undocumented and often weird memory management behaviour Apple does to improve performance and battery life, especially on iOS where they control the CPU hardware and do not have to worry much about backwards compatibility.

In summary — you should enable ARC if you haven't already. And you cannot rely on objects being "destroyed". Apple doesn't actually promise an object will be destroyed when you remove it from an array, they only tell developers their code must assume it might have been destroyed.

You have a local variable item . Variables are strong by default. So item is a strong variable. As long as that variable exists, it will take ownership of objets saved to it.

Local variables only exist as long as their scope exists. In this code:

-(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];  
}

The NSMutableArray array1 exists for the life of the method, because it's local variable is strong (The default.)

The variable array2 is also strong, but its scope is the set braces that enclose it. As soon as you get to the closing brace, the code exits that scope, so the variable is no longer owned by anybody, and gets released.

Does that help?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM