我正在解析一个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
答案 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循环语法。