Неправильное уменьшение счетчика ссылок объекта, который в данный момент не принадлежит вызывающей стороне - PullRequest
3 голосов
/ 15 марта 2011

Неправильное уменьшение счетчика ссылок на объект, который в данный момент не принадлежит вызывающей стороне на iPhone. Это происходит с NSString, которую я четко инициализирую и выпускаю в цикле for. Я попытался сделать то же самое, что и строка авто-релиза, но у меня есть утечки. Я полагаю, что виновником является вызов с указанием строки. Любые предложения, кстати, по этому не просачиваются, но я получаю предупреждение при сборке и анализе. Все также работает нормально, и приложение не падает.

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

ОБНОВЛЕНИЕ - добавлен мой класс imageLoader, который, насколько мне известно, не имеет утечки

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

Ответы [ 2 ]

5 голосов
/ 15 марта 2011

Поскольку вы переназначаете переменную imageString, ссылка на исходный объект теряется.Зачем выделять пустую строку в любом случае?Просто измените код на

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

и удалите [imageString release], и все готово.

1 голос
/ 15 марта 2011

Не отслеживайте количество ссылок как способ понимания управления памятью. Это только смущает тебя. Вещи манипулируют подсчетами ссылок ваших объектов из глубины фреймворка, и если вы будете наблюдать, как эти числа прыгают по (очевидно) без причины, вы просто сойдете с ума и опубликуете здесь серию все более и более сумасшедших вопросов, которые мы затем получим иметь дело с. Поверьте мне - мы видели это раньше.

Так что просто игнорируйте номер счетчика ссылок и убедитесь, что вы правильно удерживаете и отпускаете объекты.

...