3

このページコントロールコードは、アップルのサンプルと同じです。ここに、ImageViewを含むサブビュー(controller.view)があります。ここで問題はメモリ管理にあります。すべて正常に動作します。しかし、私が5-10ページをスクロールすると。RAMがいっぱいになります。ビュー+コントローラーを解放しようとしましたが、機能する適切な場所/方法が見つかりませんでした。現在表示されていないビューを解放したい。(現在、前、次のビューを除く)

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    NSMutableArray *controllers = [[NSMutableArray alloc] init];
    for (unsigned i = 0; i < kNumberOfPages; i++) {
        [controllers addObject:[NSNull null]];
    }
    self.viewControllers = controllers;
    [controllers release];

    scrollView.pagingEnabled = YES;
    scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * kNumberOfPages, scrollView.frame.size.height);
    scrollView.showsHorizontalScrollIndicator = NO;
    scrollView.showsVerticalScrollIndicator = NO;
    scrollView.scrollsToTop = NO;
    scrollView.delegate = self;

    pageControl.numberOfPages = kNumberOfPages;
    pageControl.currentPage = 0;

    [self loadScrollViewWithPage:0];
    [self loadScrollViewWithPage:1];
}
- (void)loadScrollViewWithPage:(int)page {
    if (page < 0) return;
    if (page >= kNumberOfPages) return;

    PageControlExampleViewControl *controller = [viewControllers objectAtIndex:page];
    if ((NSNull *)controller == [NSNull null]) {
        controller = [[PageControlExampleViewControl alloc] initWithPageNumber:page];
        [viewControllers replaceObjectAtIndex:page withObject:controller];
        [controller release];
    }

    if (nil == controller.view.superview) {
        CGRect frame = scrollView.frame;
        frame.origin.x = frame.size.width * page;
        frame.origin.y = 0;
        controller.view.frame = frame;
        [scrollView addSubview:controller.view];
    }
}

- (void)scrollViewDidScroll:(UIScrollView *)sender {
  if (pageControlUsed) {
        return;
    }
    CGFloat pageWidth = scrollView.frame.size.width;
    int page = floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
    pageControl.currentPage = page;

    [self loadScrollViewWithPage:page - 1];
    [self loadScrollViewWithPage:page];
    [self loadScrollViewWithPage:page + 1];

}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    pageControlUsed = NO;
}
- (IBAction)changePage:(id)sender {
    int page = pageControl.currentPage;
    [self loadScrollViewWithPage:page - 1];
    [self loadScrollViewWithPage:page];
    [self loadScrollViewWithPage:page + 1];
    CGRect frame = scrollView.frame;
    frame.origin.x = frame.size.width * page;
    frame.origin.y = 0;
    [scrollView scrollRectToVisible:frame animated:YES];
    pageControlUsed = YES;
}
4

4 に答える 4

4

Deepmist のコードを数時間試してみました。それは仕事をしましたが、メモリ警告を受け取り、25〜30ページがスクロールされるたびにアプリがクラッシュしました(ページで大きな画像を使用しています)。Instruments では、メモリの使用量が非常に多いことに気付きました。不要なビューがスーパービューから時々削除され、相対的な viewControllers が NSNull に置き換えられたとしても、Instruments は 4 ~ 5MB のすべてのページスクロールで実際のメモリが増加することを示しました!

Webで検索すると、これはよくある問題であることがわかりました。この問題もある場合は、次のチェックを試してください。

1) 各ビューで、必ず imageNamed の代わりに imageWithContentsOfFile を使用してください。文書化されているように、イメージに名前を付けてイメージをキャッシュし、メモリ サイズを増やします。

2) Deepmist コードで、次の後に:

[controller.view removeFromSuperview];

また、ビューを nil に設定する必要があります。

controller.view=nil;

このトリックはメモリ消費を解決し、ロードされた 3 つのビューのみで安定しています (ページ スクロールでのフラッシュを避けるため、current、current-1、current+1)。

お役に立てれば!

于 2011-06-11T17:53:05.570 に答える
1

私はこれをテストしませんでしたが、次のようにロードの反対を行うメソッドを書くことができると思います:

- (void)unloadScrollViewWithPage:(int)page {
    if (page < 0) return;
    if (page >= kNumberOfPages) return;

    PageControlExampleViewControl *controller = [viewControllers objectAtIndex:page];

    if ((NSNull *)controller != [NSNull null]) {
        if (nil != controller.view.superview)
            [controller.view removeFromSuperview];

        [viewControllers replaceObjectAtIndex:page withObject:[NSNull null]];            
    }
}

次に、次のように didScroll メソッドにコードを追加します。

[self unloadScrollViewWithPage:page - 2];
[self loadScrollViewWithPage:page - 1];
[self loadScrollViewWithPage:page];
[self loadScrollViewWithPage:page + 1];
[self unloadScrollViewWithPage:page + 2];
于 2011-03-28T21:59:46.763 に答える
0

loadScrollViewWithPage メソッドで、if (nil == controller.view.superview) の直前に、すべてのビューを循環し、現在の -1、現在、および現在の + 1 を除くすべてのビューを削除しますが、メソッドが現在のインデックス ビューで呼び出された場合のみです。また、viewControllers 配列内のこれらのビュー コントローラーを NSNull に置き換えることを忘れないでください。

于 2011-03-28T21:43:50.807 に答える
0

このVSScrollview を試してみてください。 UITableview がそのセルを再利用するように、そのビューを再利用します。

于 2013-06-24T10:51:04.290 に答える