访问 nsmutable 数组时给出 nil

发布于 2024-10-02 12:15:23 字数 4109 浏览 2 评论 0原文

我正在解析一个 json 对象并将歌曲对象存储在歌曲(一个 nsmutable 数组)中。 当我显示歌曲的图像时,即当从数组访问对象时,它给出该对象中的所有值 nil 。

在 setSongsScrollView 方法的以下代码中,在 for 循环中,当从歌曲数组访问歌曲对象时,它在调试器中显示为零,并因错误 EXEBadacess 崩溃。但该数组的计数给出了正确的值。

请问有人可以帮我吗

- (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

i am parsing a json object and storing the song objects in songs, a nsmutable array.
while am displaying the image of the song i.e. while accessing the object from the array its giving all values nil in that object.

in the following code in setSongsScrollView method, in for loop while accessing the song object from songs array its showing nill in the debugger and crashing with error EXEBadacess.But the count of that array is giving correct.

can any body help me out please

- (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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

深海不蓝 2024-10-09 12:15:23

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

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

上面的行分配您拥有的一首新歌曲,并将对其的引用分配给 thesong

thesong = [self.songs objectAtIndex:i];

上面的行将该引用替换为对您不拥有的数组中的一首歌曲的新引用。请记住:您现在不拥有该歌曲引用的歌曲。现在,您刚刚分配的对象不再有任何引用,但您仍然拥有它。因此该对象已泄漏。

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

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

Marcel has basically got the right answer but I think a little more explanation is needed. Look at the following lines from setSongsScrollView:

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

The above line allocates a new Song that you own and assigns a reference to it to thesong

thesong = [self.songs objectAtIndex:i];

The above line replaces that reference with a new reference to a song from the array that you don't own. Remember that: you do not own the song referenced by thesong now. There are now no more references left to the object you just allocated, but you still own it. The object has therefore leaked.

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

Use stringByAppendingPathComponent: to build file paths, not stringWithFormat:.

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

The last line in the above sequence releases the object referenced by thesong. As noted above, you do not own that object. You must not release it, but you have anyway. This means that, at some point, may be now, maybe later, the object will be deallocated while something (probably the array) still thinks it has a valid reference. That's what causes the crash.

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

The above method contains exactly the same error.

盛装女皇 2024-10-09 12:15:23

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

如果新歌曲已经在数组中,则不需要创建新歌曲。相反:

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

还要考虑使用 Objective-C 2.0 for-each 循环语法。

You're creating a new Song instance (thesong), then assign this very instance to a song presumably already in the array. That makes no sense at all and is probably responsible for the memory error.

You shouldn't need to be creating new Songs if they are already in the array. Instead:

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

Also look into using the Objective-C 2.0 for-each loop syntax.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文