2011-03-15 48 views
3

iPhone上的調用者未在此時擁有的對象的引用計數遞減不正確。它發生在NSString中,我明確地在for循環中初始化並釋放它。我試圖做同樣的autoreleases字符串,但我得到泄漏。我認爲罪魁禍首是字符串調用。任何建議,通過這種方式不泄漏,但我在構建和分析中得到警告。一切都很好,應用程序不會崩潰。調用者此時未擁有的對象的引用計數遞減不正確

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

看起來你可以使用一點刷新你的C指針技能。我建議學習:http://boredzo.org/pointers – 2011-03-15 14:26:07

回答

5

既然你重新分配imageString變量時,引用原始對象將丟失。爲什麼要分配一個空字符串呢?只是將代碼更改爲

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

並刪除[imageString release],你很好走。

+0

謝謝,但這給了我一個泄漏。再次可能是由於stringbytrimmingcharacters,我可以嘗試保留,然後釋放它。 – zambono 2011-03-15 16:23:03

+0

你現在正在進行'autorelease路線'。 'stringByTrimmingCharactersInSet'返回一個自動釋放的實例,你也碰巧(錯誤地)手動釋放。 – Rengers 2011-03-15 16:26:35

+0

一些更多的信息,如果我做NSString * imageString = [[[[storiesArray objectAtIndex:i] objectForKey:@「image」] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] retain];然後釋放我也得到一個泄漏,但只有當我在隊列中取消操作。 – zambono 2011-03-15 18:27:38

1

不要跟蹤引用計數來理解內存管理。這隻會讓你感到困惑。事情從框架的深處操縱你的對象的引用計數,如果你看到這些數字跳躍(顯然)沒有理由,你會瘋了,在這裏發佈一系列越來越瘋狂的問題,然後我們會有處理。相信我 - 我們以前見過。

所以只要忽略參考計數,並確保正確保留和釋放對象。

+4

由於引用計數而未發佈此問題,但是由於構建和分析中收到警告。正如你可以看到的,我分配,並在for循環內釋放。 – zambono 2011-03-15 16:29:38

相關問題