我写的照片查看应用程序有问题。
我有一个内置UINavigationController的UITabBarController。 UINavigationController最初显示UITableView。在选择时,它会推送另一个UIViewController(个人相册)以及一张NSArray照片。这个Controller包含一个UIScrollView / UIPageControl,它显示了几个UIVmageControllers,其中有一个UIImageView。
该应用程序最初效果很好。它为每个相册正确加载每个图像,您可以从导航栏返回。问题是在大约180张图像之后,应用程序开始抛出内存警告并最终崩溃抛出“程序接收信号:”0“。警告:check_safe_call:无法恢复当前帧”我认为这与低内存有关。 令人难以置信的是令人沮丧,因为我已经检查过并且没有泄漏,并且每个dealloc都被调用。 dealloc方法释放每个保留的属性并将它们设置为nil。
如果你签入了仪器,它会显示每张专辑被查看后内存使用量逐渐增加。它确实释放了一些内存,但不是全部。例如如果专辑使用1MB显示0.9MB可能会被释放。
任何帮助将不胜感激。这是我发布之前的最后一个问题。
编辑:这是基本项目文件的链接。 http://www.mediafire.com/?nztrd1yhzoo
AlbumsViewController(推送个人“albumviewcontroller”)
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSMutableDictionary *dictThisItem = [self.arrAlbums objectAtIndex:[indexPath row]];
NSString *strBand = [dictThisItem objectForKey:@"album"];
NSMutableArray *arrThesePhotos = [[self.arrAlbums objectAtIndex:[indexPath row]] objectForKey:@"photos"];
if (self.albumViewController == nil){
self.albumViewController = [[AlbumViewController alloc] initWithNibName:nil bundle:nil];
}
albumViewController.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:albumViewController animated:YES];
self.albumViewController.arrPhotos = arrThesePhotos;
[albumViewController populateScroller];
}
AlbumViewController
- (void)populateScroller {
imagesScroller.pagingEnabled = YES;
imagesScroller.contentSize = CGSizeMake(imagesScroller.frame.size.width * [self.arrPhotos count], 380);
imagesScroller.showsHorizontalScrollIndicator = NO;
imagesScroller.showsVerticalScrollIndicator = NO;
imagesScroller.scrollsToTop = NO;
imagesScroller.delegate = self;
imagesScroller.backgroundColor = [UIColor blackColor];
[imagesScroller scrollRectToVisible:CGRectMake(0.0, 0.0, 320.0, 480.0) animated:NO];
pageControl.numberOfPages = [self.arrPhotos count];
pageControl.currentPage = 0;
pageControl.backgroundColor = [UIColor blackColor];
NSMutableArray *controllers = [[NSMutableArray alloc] init];
for (int i = 0; i < [self.arrPhotos count]; i++) {
CGRect frame = imagesScroller.frame;
frame.origin.x = frame.size.width * i;
frame.origin.y = 0;
NSString *strImagePath = [[self.arrPhotos objectAtIndex:i] stringByReplacingOccurrencesOfString:@"iPhone" withString:@"iPhone_thumbnail"];
ImageViewController *imageViewController = [ImageViewController alloc];
imageViewController.localImage = YES;
imageViewController.albumViewController = self;
[imageViewController initWithPhotoName:strImagePath];
[controllers addObject:imageViewController];
imageViewController.view.frame = frame;
[imagesScroller addSubview:imageViewController.view];
[imageViewController release];
}
self.viewControllers = controllers;
[controllers release];
}
ImageViewController
- (void)viewDidLoad {
self.navigationShown = NO;
Cache *cache = [[Cache alloc] init];
[cache release];
NSString *strURL = [@"http://www.marklatham.co.uk" stringByAppendingString:self.strThisPhoto];
NSString *strTmpPrefix = (self.localImage) ? @"_tmp_rockphotothumb_" : @"_tmp_rockphotolarge_";
// Cache Paths
NSArray *arrPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *strLocalPath = [[arrPaths objectAtIndex:0] stringByAppendingString:@"/"];
NSString *strPrefix = (strTmpPrefix != nil) ? strTmpPrefix : @"_tmp_rockphotolarge_";
NSMutableArray *arrImagePaths = (NSMutableArray *)[strURL componentsSeparatedByString:@"/"];
// Check cache
NSString *strEntireLocalCache = [strLocalPath stringByAppendingString:[strPrefix stringByAppendingString:[arrImagePaths objectAtIndex:[arrImagePaths count]-1]]];
if ([[NSFileManager defaultManager] fileExistsAtPath:strEntireLocalCache]){
UIImageView *imvImageView = [UIImageView alloc];
UIImage *image = [[UIImage imageWithContentsOfFile:strEntireLocalCache] autorelease];
[imvImageView initWithImage:image];
CGSize imgSize = image.size;
CGFloat fltWidth = imgSize.width;
CGFloat fltHeight = imgSize.height;
// If landscape rotate image
if (fltWidth > fltHeight){
imvImageView.frame = CGRectMake(-80.0, 80.0, 481.0, 320.0);
CGAffineTransform rotate = CGAffineTransformMakeRotation(-1.57079633);
[imvImageView setTransform:rotate];
}else{
imvImageView.frame = CGRectMake(0.0, 0.0, 320.0, 481.0);
}
[self.view addSubview:imvImageView];
[imvImageView release];
}else{
// Data URL Downloading
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
NSData *datImageData = [NSData dataWithContentsOfURL: [NSURL URLWithString:strURL]];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
[datImageData writeToFile:strEntireLocalCache atomically:YES];
UIImageView *imvImageView = [UIImageView alloc];
UIImage *image = [[UIImage imageWithData: datImageData] autorelease];
[imvImageView initWithImage:image];
CGSize imgSize = image.size;
CGFloat fltWidth = imgSize.width;
CGFloat fltHeight = imgSize.height;
// If landscape rotate image
if (fltWidth > fltHeight){
imvImageView.frame = CGRectMake(-80.0, 80.0, 481.0, 320.0);
CGAffineTransform rotate = CGAffineTransformMakeRotation(-1.57079633);
[imvImageView setTransform:rotate];
}else{
imvImageView.frame = CGRectMake(0.0, 0.0, 320.0, 481.0);
}
[self.view addSubview:imvImageView];
[imvImageView release];
}
}
答案 0 :(得分:0)
正确使用ObjectAlloc仪器,您可以准确找到正在使用的内存的位置,从而找出内存泄漏的原因。
答案 1 :(得分:0)
确保使用仪器并检查泄漏视图。
但是,如果您确定它没有泄漏:如果您加载较少的图像,这个问题是否需要更长的时间?您可能希望尝试对图像进行下采样,以便更多地适合内存,或者仅在需要时从磁盘加载它们。
另外,在这一行:
UIImage *image = [[UIImage imageWithContentsOfFile:strEntireLocalCache] autorelease];
我认为autorelease
调用是不必要的,因为方法名称idiom +objectWithArgument:
会返回一个自动释放的对象。我不确定自动释放两次是否会在以后产生不良后果,但值得一试。尝试解决这个问题,看看是否有任何变化。
答案 2 :(得分:0)
在说服我的客户之后,我设法通过使用three20框架来解决这个问题。