0

作成した写真表示アプリケーションに問題があります。

UINavigationControllerを内部に持つUITabBarControllerがあります。UINavigationControllerは、最初にUITableViewを表示します。選択すると、NSArrayの写真とともに別のUIViewController(個別のフォトアルバム)がプッシュされます。このコントローラーには、UIImageViewが存在するいくつかのUIViewControllerを表示するUIScrollView/UIPageControlが含まれています。

アプリケーションは最初はうまく機能します。アルバムごとに各画像が正しく読み込まれ、ナビゲーションバーから戻ることができます。問題は、約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];

}

}
4

3 に答える 3

0

ObjectAlloc Instrumentを適切に使用すると、使用されているメモリの場所を正確に特定できるため、メモリリークの原因を特定できます。

于 2009-12-23T23:16:07.087 に答える
0

Instrumentsを使用し、リークビューを確認してください。

しかし、リークしていないことが確実な場合:ロードする画像の数が少ない場合、この問題の発生に時間がかかりますか?より多くのメモリに収まるように画像をダウンサンプリングするか、必要な場合にのみディスクから画像をロードすることをお勧めします。

また、この行では:

UIImage *image = [[UIImage imageWithContentsOfFile:strEntireLocalCache] autorelease];

メソッド名イディオムは自動解放されたオブジェクトを返すautoreleaseため、この呼び出しは不要だと思います。+objectWithArgument:2回の自動リリースが後で悪い結果をもたらす可能性があるかどうかはわかりませんが、一見の価値があります。それを取り出して、何かが変わるかどうかを確認してください。

于 2009-12-23T23:31:57.053 に答える
0

クライアントを説得した後、私はthree20フレームワークを使用してこれを回避することができました。

于 2010-01-21T20:51:51.353 に答える