【问题标题】:A reliable way to get UIPageViewController current index获取 UIPageViewController 当前索引的可靠方法
【发布时间】:2016-04-26 06:57:43
【问题描述】:

我正在寻找一种可靠的方法来跟踪 UIPageViewController 当前索引。

这个问题是众所周知的;尽管 viewController 被正确呈现,但很难跟踪当前索引。

我认为在 SO 社区中刷新这个主题会很好,因为由于某种原因它仍未解决

我在这里浏览了很多帖子,但大多数答案都已过时或被标记为不可靠(结果取决于用户是完全滑动还是只滑动了一半等)

我访问过this 线程,但它没有提供任何明确正确的答案。

我试过了:

1) 跟踪 viewController 的视图标签 - link - 总是返回 0

2) 在两个 UIPageViewController 方法中查看索引变量,viewControllerBeforeViewControllerviewControllerAfterViewControlle

它的结果是不可预测的,有时它会跳过一个索引等。

有没有人想出一个好方法,可靠的方法来跟踪 UIPageCiewController 索引以利用它(例如打印当前索引)?

我很欣赏 obj-c 和 swift 的实现,但 swift 是我正在寻找的。​​p>

【问题讨论】:

  • 我在该链接中有一个答案,但不幸的是我的答案没有任何赞成票,但使用委托是(至少对我而言)正确跟踪索引的唯一方法。如果您想查看我的实现(ObjC),请告诉我...
  • 我认为@0yeoj 解决方案是您正在寻找的:stackoverflow.com/a/33818615/2301271
  • @0yeoj 随时在这里发布你的实现,最好是在 swift 中

标签: ios objective-c swift uipageviewcontroller


【解决方案1】:

这是给ObjC

父视图控制器

#import "PagesViewController.h"

// Delegate: PageViewDelegate
// Declared inside `PagesViewController`
//
@interface ParentViewController () <UIPageViewControllerDataSource, UIPageViewControllerDelegate, PageViewDelegate>

@property (nonatomic) UIPageViewController *pageViewController;

@end

@implementation ViewController

- (void)viewDidLoad 
{
    [super viewDidLoad];

    self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
    self.pageViewController.dataSource = self;
    self.pageViewController.view.frame = self.view.frame;

    // im setting page 3 as the default page
    //
    [self.pageViewController setViewControllers:[NSArray arrayWithObject:[self viewControllerAtIndex:3]] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];
    [self addChildViewController:self.pageViewController];
    [self.view addSubview:self.pageViewController.view];
}

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController 
{
    NSUInteger index = [(PagesViewController *)viewController index];

    if (index == 0) {
        return nil;
    }

    index--;

    return [self viewControllerAtIndex:index];
}

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {

    NSUInteger index = [(PagesViewController *)viewController index];

    index++;

    if (index == 5) {
        return nil;
    }

    return [self viewControllerAtIndex:index];
}

- (PagesViewController *)viewControllerAtIndex:(NSInteger)index
{
    PagesViewController *vc = [[PagesViewController alloc] init];

    // set delegate here..
    //
    vc.delegate = self;

    // other data
    //
    vc.index = index;
    vc.titleLabel = [NSString stringWithFormat:@"Screen :%ld", (long)index];

    return vc;
}

- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController 
{ // The number of items reflected in the page indicator. return x; }

- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController
{ // The selected item reflected in the page indicator. return x; }

// This is what you need
//
- (void)viewController:(id)VC didShowWithIndex:(long)index
{
    NSLog(@"didShowWithIndex: %ld", index);
}

PagesViewController.h

@protocol PageViewDelegate <NSObject>

- (void)viewController:(id)VC didShowWithIndex:(long)index;

@end


@interface PagesViewController : UIViewController

@property (weak) id <PageViewDelegate> delegate;

@property (nonatomic) NSInteger index;

@property (nonatomic) NSString *titleLabel;

@end

PagesViewController.m

@implementation PagesViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.view.backgroundColor = [UIColor blackColor];

    UILabel *titleLabel = [[UILabel alloc] initWithFrame:self.view.frame];
    titleLabel.textAlignment = NSTextAlignmentCenter;
    titleLabel.textColor = [UIColor whiteColor];
    titleLabel.text = self.titleLabel;
    [self.view addSubview:titleLabel];
}

// Trigger delegate here
//
- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    [self.delegate viewController:self didShowWithIndex:self.index];
}

@end

【讨论】:

    【解决方案2】:

    就像@0yeoj 建议的那样,委托设计模式是这里的解决方案。这需要一些跳出框框的思考。

    让我们添加协议 IndexDelegate 并修改一点 PageContentViewController

    protocol IndexDelegate {
    func showIndex(index:Int)
     }
    
    import UIKit
    
    class PageContentViewController: UIViewController {
    
    @IBOutlet weak var imageView: UIImageView!
    var delegate:IndexDelegate?
    var pageIndex:Int = 0
    var imageFile:String!
    override func viewDidLoad() {
        super.viewDidLoad()
        self.imageView.image = UIImage(named: self.imageFile)
        }
    override func viewDidAppear(animated: Bool) {
        self.delegate!.showIndex(self.pageIndex)
        }
    

    现在在我们的父视图控制器中,我们遵守协议

    func showIndex(index: Int) {
      print(index)
      }
    

    别忘了设置yourPageContentViewControllerInstance.delegate = self 并继承协议YourParentViewController:UIViewController, UIPageViewControllerDataSourceDelegate, IndexDelegate {}

    就是这样!完美可靠地运行,完全不会滞后!

    【讨论】:

    • 您好 DCDC,您将“yourPageContentViewControllerInstance.delegate = self”放在哪里。您是否遍历所有 VController 并分配委托 = 父级?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-12
    • 2011-10-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多