0

写真アプリと同様の方法で UIScroller に複数の UIImageView を表示するための小さなアプリケーションがあります。アイテムを選択すると、(配列に追加された) 写真の XML ドキュメントを解析し、画像を表示する UIViewController を追加する TableView があります。

問題は、タブバー項目をクリックすると、画像を表示するビューを削除し、使用されているすべてのメモリの割り当てを解除した後、TableView に戻る必要があるタブバーコントローラーがあることです。問題は、これを達成する方法を理解できないことです。記憶のルールの理解不足なのか、私にはわかりません。

これが私が問題を抱えているプロセスです。

テーブル ビュー コントローラー

これは、parserDidEndDocument: の後に呼び出されます。backToMenu は、タブ バー アイテムから呼び出されます。

@interface AlbumsViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {
    AlbumViewController *albumViewController;
}
@property (nonatomic, retain) AlbumViewController *albumViewController;


- (void)displayPhotos {
    albumViewController = [[AlbumViewController alloc] initWithNibName:@"AlbumView" bundle:nil];

    albumViewController.parentView = self;
    albumViewController.arrPhotos = self.arrCurrentSetOfPhotos;

    [self.view addSubview:albumViewController.view];

    [albumViewController populateScroller];
}

- (void)backToMenu {
    [albumViewController.view removeFromSuperview];
}

アルバム ビュー コントローラー

これは、UIScroller と UIPageControl を含む UIViewController です。いくつかの ImageViewControllers を追加します。

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

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

        ImageViewController *imageViewController = [ImageViewController alloc];
        imageViewController.localImage = YES;
        [imageViewController initWithPhotoName:strImagePath];
        [controllers addObject:imageViewController];

        imageViewController.view.frame = frame;
        [imagesScroller addSubview:imageViewController.view];

        [imageViewController release];

    }

    self.viewControllers = controllers;
    [controllers release];

}

ImageViewController

これには1つの方法があります。UIImageView の追加を処理する ImageView と呼ばれるサブクラス化された UIView を追加します。

- (void)loadImage {

    NSString *strRootURL = @"http://www.marklatham.co.uk";

    CGRect rect = CGRectMake(0.0, 0.0, 320.0, 480.0);

    ImageView *imageView = [ImageView alloc];
    imageView.strURL = [strRootURL stringByAppendingString:self.strThisPhoto];
    imageView.strTmpPrefix = (self.localImage) ? @"_tmp_rockphotothumb_" : @"_tmp_rockphotolarge_";
   [imageView initWithFrame:rect];

   [self.view addSubview:imageView];

   [imageView release];
}

backToMenu 関数は、AlbumViewController を削除/割り当て解除し、すべての子サブビューで delloc を呼び出して、使用済みメモリを解放することになっています。

どこが間違っていますか?どんな助けでも大歓迎です。

ありがとう。

4

2 に答える 2

2

AlbumViewController はまだビューへの参照を保持しているため、その参照を解放するまで解放されません。しかし、これは良いことです。

ユーザーが画面を変更するたびにメモリを解放する必要はありません。異なるビュー間を行ったり来たりすると、物事が遅くなるだけです。システムのメモリが不足すると、すべてのビュー コントローラーで didReceiveMemoryWarning が呼び出され、ビューが表示されていない場合はビューが解放されます。

albumViewController の割り当て/解放方法についてもう少し賢くしたいだけです

- (void)displayPhotos {
    ////// Only create this view controller if it doesn't exist yet
    if(albumViewController == nil) {
        albumViewController = [[AlbumViewController alloc] initWithNibName:@"AlbumView" bundle:nil];
    }

    albumViewController.parentView = self;
    albumViewController.arrPhotos = self.arrCurrentSetOfPhotos;

    [self.view addSubview:albumViewController.view];

    [albumViewController populateScroller];
}

- (void)backToMenu {
    [albumViewController.view removeFromSuperview];
    //// if you don't do this, you'll have a retain cycle between the two
    //// view controllers and neither will ever get released
    albumViewController.parentView = nil;
}

- (void)didReceiveMemoryWarning {
    ///// if the albunViewController isn't in use, go ahead and free its memory
    if([self.albumViewController isViewLoaded] && self.albumViewController.view.superview == nil) {
        self.albumViewController = nil;
    }
    [super didReceiveMemoryWarning];
}

また、AlbumsViewController から populateScrollers を呼び出す代わりに、AlbumViewController の setArrPhotos メソッドで呼び出しますが、arrPhotos が変更された場合のみです。例えば:

- (void)setArrPhotos:(NSArray *)newArrPhotos {
    if(newArrPhotos != arrPhotos)
    {
        [arrPhotos release];
        arrPhotos = [newArrPhotos retain];
        [self populateScrollers];
    }
}

こうすることで、ユーザーが同じアルバムを何度も表示するようになった場合でも、同じビュー階層を何度も再作成する必要がなくなります。

于 2009-12-13T23:53:57.607 に答える
0

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

于 2010-01-21T20:48:21.067 に答える