1

ユーザーがテーブルビューに持っているオブジェクトの数に応じて、スクロールビューに多くのビューコントローラーをロードしたアプリがあります。したがって、テーブルビューとスクロール ビューを切り替えると、ユーザーがテーブルビューに持っているオブジェクトの数に応じて、スクロール ビューのビュー コントローラーの数が変わります。

Apple の PageControl サンプル コードのコードを使用して、いくつかの変更を加えた後、内部に多数のビュー コントローラーを含むスクロール ビューを作成します。

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

   // replace the placeholder if necessary
   MainViewController *countdownController = [viewControllers objectAtIndex:page];
   if ((NSNull *)countdownController == [NSNull null]) 
   {

      id occasion = [eventsArray objectAtIndex:page];

      countdownController = [[MainViewController alloc] initWithPageNumber:page];
      [countdownController setOccasion:occasion];

      [viewControllers replaceObjectAtIndex:page withObject:countdownController];


      [countdownController release];

    }

    // add the controller's view to the scroll view
    if (nil == countdownController.view.superview) 
    {
      CGRect frame = scrollView.frame;
      frame.origin.x = frame.size.width * page;
      frame.origin.y = 0;
      countdownController.view.frame = frame;
      [scrollView addSubview:countdownController.view];
    }

}

問題は、もちろんメモリの問題を引き起こす新しいオブジェクトを追加しなかったにもかかわらず、テーブル ビューとスクロール ビュー (Instruments によると) を切り替えると、生きているビュー コントローラー (ここでは MainViewController) の数が増え続けることです。

私はスクロールビューのviewWillDisappearで非常に多くのことを試しました:

- (void) viewWillDisappear:(BOOL)animated
{


    //test unloading all views
    //Remove all subviews
    [[scrollView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];

    //[[scrollView subviews] makeObjectsPerformSelector:@selector(release)];


    //[viewControllers removeAllObjects];
    for (unsigned m = 0; m < [viewControllers count]; m++)
    {
     //[[viewControllers objectAtIndex:m] makeObjectsPerformSelector:@selector(release)];

      [viewControllers removeObjectAtIndex:m];
    }
 }

しかし、うまくいきませんでした。これは、アプリがどのように機能するかの記録です youtube.com/watch?v=5W8v_smZSog

これは、スクロール ビューの viewWillAppear メソッドです。

- (void)viewWillAppear:(BOOL)animated
{

    eventsArray = [[NSMutableArray alloc] init];

    kNumberOfPages = [self.dataModel occasionCount];

    //update the eventsArray from the dataModel
    //Fill in the events Array with occasions form the data model
    for (unsigned r = 0; r < kNumberOfPages; r++)
    {
        Occasion* occasion = [self.dataModel occasionAtIndex:r];
        [eventsArray insertObject:occasion atIndex:r];
    }

     // view controllers are created lazily
     // in the meantime, load the array with placeholders which will be replaced on   demand
    NSMutableArray *controllers = [[NSMutableArray alloc] init];
    for (unsigned i = 0; i < kNumberOfPages; i++)
    {
        [controllers addObject:[NSNull null]];
     }

    self.viewControllers = controllers;
    [controllers release];

    // a page is the width of the scroll view
    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 = currentPage;

    [self loadScrollViewWithPage:0];
    [self loadScrollViewWithPage:1];
}

更新: インストゥルメントのビデオ録画http://www.youtube.com/watch?v=u1Rd2clvMQE&feature=youtube_gdata_player

そして、責任ある呼び出し元を示すスクリーン ショット: ここに画像の説明を入力

ありがとうございました。

4

4 に答える 4

2

これは、使用したくない場合に使用しますUIPageViewController(他の回答を読んでください)。

サンプルプロジェクトは、一定のページ数(kNumberOfPages)用に設計されています。scrollviewコンテンツのサイズとviewcontroller配列のサイズは、ページ数によって異なります。サンプルコードは、これをawakeFromNibで設定します。これは1回だけ呼び出されます。

したがって、これを動的にするために、ページ数が変更されたときにContentController全体を再作成できます。ページ数のプロパティを追加するだけです。

もう1つのオプションは、ページ数が変更されたときに、scrollviewとviewcontrollerの配列をリセットすることです。

イベントのプロパティを定義したと仮定します。

@property(nonatomic,retain) NSArray* eventsArray;

次に、次のようなセッターメソッドを追加できます。

-(void)setEventsArray:(NSArray *)eventsArray
{
    if (eventsArray != _eventsArray) {
        [_eventsArray release];
        _eventsArray = [eventsArray retain];
        NSUInteger eventCount = [eventsArray count];
        //reset scrollview contentSize
        scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * eventCount, scrollView.frame.size.height);

        // reset content offset to zero
        scrollView.contentOffset = CGPointZero;

        //remove all subviews
        [[scrollView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];

        pageControl.numberOfPages = eventCount;

        // reset viewcontroller array
        NSMutableArray *controllers = [[NSMutableArray alloc] init];
        for (unsigned i = 0; i < eventCount; i++)
        {
            [controllers addObject:[NSNull null]];
        }
        self.viewControllers = controllers;
        [controllers release];

        [self loadScrollViewWithPage:0];
        [self loadScrollViewWithPage:1];
    }
}

このメソッドは、ユーザーがスクロールビューに切り替えたときに、テーブルビューコントローラーから呼び出します。

于 2012-11-03T11:02:01.960 に答える
2

Apple の PageControl サンプル コードは 2 年前のものであり、これをすべて実行する新しいコンテナー ビュー コントローラーが iOS 5 にあるため、廃止されたと見なすことができます: UIPageViewController.

を実際に使い始めるUIPageViewController必要があります。そうすれば、その loadScrollViewWithPage メソッドはまったく必要ありません。コードが少なくなり、より簡単になります。

PhotoScrollerのサンプル コードを見てみましょう。を最大限に活用するために更新されましたUIPageViewController

于 2012-11-02T22:25:46.550 に答える
1

Apple のView Controller Containment praticsを実装しているようには見えません。これにより、メモリ管理がはるかに簡単かつ安全になります。

さらに、将来の頭痛の種を大幅に節約できることを期待して、あなたが説明していることを行うオープンソースプロジェクトがすでにあります(任意の数のView Controllerの自己管理スクロールビューを実装しています)。

あなたはそれを見たいと思うかもしれません: RHHorizo​​ntalSwipe

于 2012-11-02T22:05:33.367 に答える
1

複数の UIViewController ビューを含む UIScrollView の概念は、せいぜい大ざっぱに聞こえますが、その設計はまったく良くありません。

そうは言っても、潜在的な問題の 1 つは次の行である可能性があります。

if ((NSNull *)countdownController == [NSNull null]) 

次のような方がよいでしょう。

if (!countdownController || [countdownController isKindOfClass:[NSNull class]])

また、メソッドを呼び出す必要が[super viewWillDisappear:animated]ありますviewWillDisappear

于 2012-11-04T14:49:28.533 に答える