Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

removeObjectAtIndex causes "message sent to deallocated instance"

I am converting some code to ARC. The code searches for an element in an NSMutableArray, then finds, removes, and returns that element. The problem is that the element gets deallocated immediately upon "removeObjectAtIndex":

- (UIView *)viewWithTag:(int)tag
{
    UIView *view = nil;
    for (int i = 0; i < [self count]; i++)
    {
        UIView *aView = [self objectAtIndex:i];
        if (aView.tag == tag) 
        {
            view = aView;
            NSLog(@"%@",view); // 1 (view is good)
            [self removeObjectAtIndex:i];
            break;
        }
    }
    NSLog(@"%@",view); // 2 (view has been deallocated)
    return view;
}

When I run it, I get

*** -[UIView respondsToSelector:]: message sent to deallocated instance 0x87882f0

at the second log statement.

Pre-ARC, I was careful to retain the object before calling removeObjectAtIndex:, and then to autorelease it. How do I tell ARC to do the same thing?

like image 780
lewisanderson Avatar asked Oct 27 '11 06:10

lewisanderson


1 Answers

Declare the UIView *view reference with the __autoreleasing qualifier, like so:

- (UIView *)viewWithTag:(int)tag
{
    __autoreleasing UIView *view;
    __unsafe_unretained UIView *aView;

    for (int i = 0; i < [self count]; i++)
    {
        aView = [self objectAtIndex:i];
        if (aView.tag == tag) 
        {
            view = aView;
            //Since you declared "view" as __autoreleasing,
            //the pre-ARC equivalent would be:
            //view = [[aView retain] autorelease];

            [self removeObjectAtIndex:i];
            break;
        }
    }

    return view;
}

__autoreleasing will give you exactly what you want because on assignment the new pointee is retained, autoreleased, and then stored into the lvalue.

See the ARC reference

like image 122
Jacob Relkin Avatar answered Oct 17 '22 16:10

Jacob Relkin