Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Incorrect decrement of the reference count of an object that is not owned at this point by the caller

Incorrect decrement of the reference count of an object that is not owned at this point by the caller on iPhone. It is happening with NSString which I clearly init and release within the for loop. I have tried to do the same as an autoreleases string but I get leaks. I assume the culprit is the stringbytrimming call. Any suggestions, by the way this does not leak, but I get the warning in build and analyze. Everything also works fine and the app does not crash.

for(int i=0;i<storyQuantity;i++) {
            NSString *imageString = [[NSString alloc] init];
            imageString = [[[storiesArray objectAtIndex:i] objectForKey: @"image"] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];  // must add trimming to remove characters

            imageLoader *imageOperation = [[imageLoader alloc] initWithImageURL:imageString target:self action:@selector(didImageLoad:) number:i];

            AppDelegate_iPad *appDelegate = [[UIApplication sharedApplication] delegate];
            [appDelegate.queue_ addOperation:imageOperation];
            [imageOperation release];
            [imageString release];
        }

UPDATE - added my imageLoader class, which to the best of my knowledge does not have a leak

- (id)initWithImageURL:(NSString *)url target:(id)target action:(SEL)action number:(int)number {
    if(self = [super init]) {
        _action = action;
        _target = target;
        _number = number;
        if(url == nil) {
            return nil;
        } else {
            _imgURL = [[NSURL alloc] initWithString:[url copy]];
        }
    }
    return self;
}

- (id)main {

    NSAutoreleasePool *pool = [NSAutoreleasePool new];

    if ([self isCancelled]) {
        NSLog(@"OPERATION CANCELLED");
        [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
        [pool drain];
        return nil;
    } else {

        [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;

        NSData *imgData = [[NSData alloc] initWithContentsOfURL:_imgURL];
        UIImage *image = [[UIImage alloc] initWithData:imgData];
        [imgData release];

        if ([self isCancelled]) {
            NSLog(@"OPERATION CANCELLED");
            [image release];
            [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
            [pool drain];
            return nil;
        } else { 

            NSNumber *tempNumber = [NSNumber numberWithInt:_number];
            NSDictionary *tempDict = [NSDictionary dictionaryWithObjectsAndKeys:tempNumber, @"number", image, @"image", nil];
            [image release];

            if([_target respondsToSelector:_action])
                [_target performSelectorOnMainThread:_action withObject:tempDict waitUntilDone:NO];
        }
    }

    [pool drain];
    return nil;

}

- (void)dealloc {
    [_imgURL release];
    [super dealloc];
}
like image 299
zambono Avatar asked Dec 04 '25 14:12

zambono


1 Answers

Since you are reassigning the imageString variable, the reference to the original object is lost. Why allocate an empty string anyway? Just change the code to

NSString *imageString = [[[storiesArray objectAtIndex:i] objectForKey: @"image"]
   stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

and remove the [imageString release] and you're good to go.

like image 64
Alfonso Avatar answered Dec 07 '25 05:12

Alfonso



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!