1

それぞれが独自のUIViewControllerによって管理される多くのUIViewを含むページングが有効になっているUIScrollViewに関する質問があります。

現在、UIScrollViewに含めることができるUIViewControllerは約20〜30個あります。これはiPadのカタログアプリで、最初からすべてのビューのプリロードを開始しましたが、UIViewControllerの量がどんどん大きくなっているため、これはオプションではなくなりました。

私はメモリ使用量の点で完璧な解決策を探しています。ScrollViewのContentOffsetが特定のコントローラーに到達したときに、UIViewControllersをリロードすることは問題ありません。そして、ContentOffsetがUIViewControllersはもう必要ないと言ったときに、UIViewControllersをゼロにすることもそれほど難しくないと思います。

これを処理する正しい方法は何ですか?UIViewControllerを必要に応じて割り当て、NSMutableDictionaryまたはNSMutableArrayに配置し、不要になったときにnilにするだけで十分ですか?すでに似たようなことをした人からの少しの助けは素晴らしいでしょう!

ご協力いただきありがとうございます!

4

1 に答える 1

5

そこにはいくつかの優れた無限スクロールクラスがあると確信していますが、「自分でロール」する場合は、現在、前、次のページを維持しながら、無限スクロールのプロセスを示す最小限のコードを次に示します。メモリ内にありますが、他のものを手放します。これは、次のことを前提としています。

  • 水平スクロールを実行していて、ページングをオンにしています。
  • 子ビューにビューコントローラを使用していること。
  • 子ViewControllerクラスには、pageそれがどのページを対象としているかを追跡するためのプロパティがあります。と
  • ビューコントローラをスクロールビューのデリゲートにしました

したがって、次のようになります。

- (void)viewDidLoad
{
    [super viewDidLoad];

    // my underlying model is just an array of strings, which I'll show on my child
    // view; your model will be more elaborate, but I just want to illustrate the concept

    self.objects = @[@"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9"];

    // set the `contentSize` for the scrollview

    CGRect content = self.view.bounds;
    content.size.width *= [self.objects count]; // make it wide enough to hold everything
    self.scrollView.contentSize = content.size;

    // set our current page and load the first pages (the first and the next pages)

    self.currentPage = 0;
    [self addChildPage:0 toScrollView:self.scrollView];
    [self addChildPage:1 toScrollView:self.scrollView];
}

- (void)addChildPage:(NSInteger)page toScrollView:(UIScrollView *)scrollView
{
    // create the child controller

    ChildViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"child"];

    // set whatever properties you need to in order for it to present its information correctly

    controller.text = self.objects[page];
    controller.page = page;

    // now do the stuff to add it to the right place in the scrollview

    CGRect frame = self.view.bounds;
    frame.origin.x = frame.size.width * page;
    controller.view.frame = frame;
    [self addChildViewController:controller];        // containment call for adding child view controller
    [scrollView addSubview:controller.view];
    [controller didMoveToParentViewController:self]; // containment call when done adding child
}

- (ChildViewController *)childControllerForPage:(NSInteger)page
{
    for (ChildViewController *controller in self.childViewControllers)
    {
        if (controller.page == page)
            return controller;
    }

    return nil;
}

- (void)addChildIfNecessary:(NSInteger)page toScrollView:(UIScrollView *)scrollView
{
    if (page < 0 || page >= [self.objects count])
        return;

    ChildViewController *controller = [self childControllerForPage:page];

    if (controller == nil)
        [self addChildPage:page toScrollView:scrollView];
}

- (void)removeChildController:(UIViewController *)controller
{
    [controller willMoveToParentViewController:nil];  // containment call before removing child
    [controller.view removeFromSuperview];
    [controller removeFromParentViewController];      // containment call to remove child
}

- (void)updateChildrenViewsForPage:(NSInteger)page forScrollView:(UIScrollView *)scrollView
{
    if (page == self.currentPage)
        return;

    // add child pages as necessary

    [self addChildIfNecessary:page     toScrollView:scrollView];
    [self addChildIfNecessary:(page-1) toScrollView:scrollView];
    [self addChildIfNecessary:(page+1) toScrollView:scrollView];

    // find any pages that need removing

    NSMutableArray *pagesToRemove = [NSMutableArray array];
    for (ChildViewController *controller in self.childViewControllers)
    {
        if (controller.page < (page - 1) ||
            controller.page > (page + 1))
        {
            [pagesToRemove addObject:controller];
        }
    }

    // remove them if they need removing

    for (UIViewController *controller in pagesToRemove)
    {
        [self removeChildController:controller];
    }

    // update our "current page" index

    self.currentPage = page;
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    NSInteger page = scrollView.contentOffset.x / scrollView.frame.size.width + 0.5;

    [self updateChildrenViewsForPage:page forScrollView:scrollView];
}

これは、適切なカスタムコンテナ呼び出しとスクロールイベントの処理を示しています。これがお役に立てば幸いです。

于 2013-03-25T19:31:20.437 に答える