Dustin
Dustin

Reputation: 6803

ARC weird deallocation behavior in UITableView

I've had this behavior happen to me twice recently and I was wondering what the root cause of the problem is (aka how do I make sure this never happens so I don't have to waste a ton of time fixing it).

When I allocate something inside of a tableview cell that is slated for reuse, once another cell is loaded and the table reloads, sometimes that object is deallocated.

Example:

SubHolder *dataStorage;

- (void) initializeLicenseTable
    {
        LicenseCell *sampleLicense = [LicenseCell new];
        self.licenseData = [[NSMutableArray alloc] initWithObjects:sampleLicense, nil];
        nib = [UINib nibWithNibName:@"LicenseCell" bundle:nil];

    if (dataStorage == nil)
    {
        dataStorage = [SubHolder new];
        dataStorage.owner = self;
        [dataStorage addStorageLocation];
    }
} //cellForRowAtIndexPath and stuff

This code doesn't work without the if statement (it causes a dataStorage to become a zombie)

What causes this behavior? It seems like testing if dataStorage is nil and only then allocating it is the opposite of what should fix a zombie problem.

-EDIT-

If this behavior is caused by sharing of the variables, how can I make it so that each time an instance of this object is created it makes its own data storage object? Each table has its own information, which is not shared with other tables.

Upvotes: 0

Views: 339

Answers (2)

sergio
sergio

Reputation: 69047

Since dataStorage is a global variable (visible in the file scope of your class), it will be shared by all the instances of your class.

Now, if a second instance of your class is initialized and you don't check for

if (dataStorage == nil)

then your global object will be overwritten and thus at some point deallocated through ARC. If some other object had stored its value somewhere, it will try to access the old object and you get the zombie access.

EDIT:

if each object needs its own dataStorage, you will simply need to declare

SubHolder *dataStorage;

in your interface declaration, or a property like:

@property (nonatomic, strong) SubHolder *dataStorage;

Upvotes: 2

jhabbott
jhabbott

Reputation: 19321

It looks like you're just creating new cells all the time instead of reusing them.

You should re-use cells like this:

UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:@"myCell"];
if(cell == nil) 
{
    cell = [[UITableViewCell alloc] initWithStyle:aStyle reuseIdentifier:@"myCell"];
}

Upvotes: 1

Related Questions