在访问nsmutablearray时给出nil

时间:2010-11-10 20:49:38

标签: iphone objective-c null

我正在解析一个json对象并将歌曲对象存储在歌曲中,这是一个可移动的数组。 当我显示歌曲的图像时,即从阵列访问对象时,它在该对象中给出所有值为零。

在setSongsScrollView方法的下面的代码中,在for songs循环中同时从songs数组中访问歌曲对象时,它在调试器中显示nill并且出现错误EXEBadacess.But该数组的计数是正确的。

任何人都可以帮助我

- (void)viewWillAppear:(BOOL)animated{ 
 [super viewDidLoad];
 [self parsingTheStation];
 [self load_images];
 [self setSongsScrollView];
}

/*
 // Implement loadView to create a view hierarchy programmatically, without using a nib.
 - (void)loadView {
 }
 */


- (void)parsingTheStation{
 NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http:...."]];
 NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
 NSString *jsonString = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
 NSData *jsonData = [jsonString dataUsingEncoding:NSUTF32BigEndianStringEncoding];
 NSDictionary *dictionary = [[CJSONDeserializer deserializer] deserializeAsDictionary:jsonData error:nil];

 songs =[[NSMutableArray alloc]init];
 NSArray *songObjects = [dictionary objectForKey:@"songs"];
 for(NSDictionary *s in songObjects){
  aSong = [[Song alloc] init];
  aSong.artist = [s objectForKey:@"by"];
  aSong.genre = [s objectForKey:@"genre"];
  aSong.cover = [s objectForKey:@"cover"];
  aSong.song_id = [s objectForKey:@"id"];
  aSong.rank = [s objectForKey:@"rank"];
  aSong.title = [s objectForKey:@"title"];
  aSong.link = [s objectForKey:@"link"];
  [songs addObject:aSong];
  [aSong release];  
 }

 NSLog(@"total number of songs is : %d",[songs count]);

}

-(void)setSongsScrollView {
 songsContainer = [[UIScrollView alloc]init];
 int songsCount = [self.songs count];
 //totla no. of songs we get +4
 int tSongs = songsCount+4;
 int n = sqrt(tSongs);
 int p = n,q = n;
 int remSongs = tSongs-(n*n);
 if(remSongs >= n){
  q = q+(remSongs/n);
  if((remSongs%n)>0)
   q++;
 }else q++;
 for(int i=0;q>p;i++){
  q--;
  p++;
 }

 NSLog(@"total songs..%d",tSongs);
 NSLog(@"total rows..%d",q);
 NSLog(@"total columns..%d",p); 

 songsContainer.contentSize = CGSizeMake(120*q, 120*p);
 int x =0, y=240, col=1;
 for(int i=0;i<songsCount;i++){
  CGRect imgFrame = CGRectMake(x, y, 118, 118);
  NSLog(@"songs conunt ...%d",[songs count]);
  Song *thesong = [[Song alloc]init];
  thesong = [self.songs objectAtIndex:i];
  NSString *filename = [NSString stringWithFormat:@"%@/%@", [LazyImageView dataPath], [thesong.cover lastPathComponent]];
  UIImageView *tempImg = [[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:filename]];
  tempImg.tag = i;
  tempImg.frame = imgFrame;
  [songsContainer addSubview:tempImg];
  [tempImg release];
  [thesong release];

  y += 120;
  if(y>=(120*p)){
   NSLog(@"total y..%d",y);
   col++;
   x += 120;
   if(col>=3)
    y=0;
   else 
    y=240;
  }  
 }
 NSLog(@"total y..%d",y);
 NSLog(@"content size..%d,%d",120*q,120*p);
}

-(void)load_images{
 for(int i=0;i<[songs count];i++){
  Song *rsong = [[Song alloc]init];
  rsong = [self.songs objectAtIndex:i];
  lazyBigImg = [[LazyImageView alloc] init];
  NSURL* url = [NSURL URLWithString:rsong.cover];
  [lazyBigImg loadImageFromURL:url];
  [lazyBigImg release];
  [rsong release];
 }
}

/*
 // Override to allow orientations other than the default portrait orientation.
 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
 // Return YES for supported orientations
 return (interfaceOrientation == UIInterfaceOrientationPortrait);
 }
 */

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}


- (void)dealloc {
 [songs release];
 [lazyBigImg release];
 [onAirBtn release];
 [chartsBtn release];
 [dealsBtn release];
 [searchBtn release];
 [stNameLbl release];
 [aSong release];
 [songsContainer release];
    [super dealloc];
}


@end

2 个答案:

答案 0 :(得分:2)

马塞尔基本上得到了正确答案,但我认为需要更多解释。请查看setSongsScrollView中的以下行:

Song *thesong = [[Song alloc]init];

以上一行分配您拥有的新歌曲并将其引用分配给该歌曲

thesong = [self.songs objectAtIndex:i];

上面的代码用来自您不拥有的数组中的歌曲的新引用替换该引用。请记住:您现在不拥有thesong引用的歌曲。现在没有更多的引用留给您刚刚分配的对象,但您仍然拥有它。因此该对象泄露了。

NSString *filename = [NSString stringWithFormat:@"%@/%@", [LazyImageView dataPath], [thesong.cover lastPathComponent]];

使用stringByAppendingPathComponent:构建文件路径,而不是stringWithFormat:

UIImageView *tempImg = [[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:filename]];
tempImg.tag = i;
tempImg.frame = imgFrame;
[songsContainer addSubview:tempImg];
[tempImg release];
[thesong release];

上面序列中的最后一行释放了thesong引用的对象。如上所述,您不拥有该对象。你不能释放它,但无论如何你都有。这意味着,在某些时候,可能是现在,也许是稍后,对象将被释放,而某些东西(可能是数组)仍然认为它具有有效的引用。这就是导致崩溃的原因。

-(void)load_images{
 for(int i=0;i<[songs count];i++){
  Song *rsong = [[Song alloc]init];
  rsong = [self.songs objectAtIndex:i];
  lazyBigImg = [[LazyImageView alloc] init];
  NSURL* url = [NSURL URLWithString:rsong.cover];
  [lazyBigImg loadImageFromURL:url];
  [lazyBigImg release];
  [rsong release];
 }
}

上述方法包含完全相同的错误。

答案 1 :(得分:1)

您正在创建一个新的Song实例(thesong),然后将此实例分配给可能已在数组中的歌曲。这完全没有意义,可能是造成内存错误的原因。

如果新歌已经在阵列中,则无需创建新歌。代替:

Song *thesong = [self.songs objectAtIndex:i];

另请参阅使用Objective-C 2.0 for-each循环语法。