获取 UIPageViewController 当前索引的可靠方法
A reliable way to get UIPageViewController current index
我正在寻找一种可靠的方法来跟踪 UIPageViewController 当前索引。
这个问题众所周知;尽管 viewControllers 被正确显示,但很难跟踪当前索引。
我认为在 SO 社区刷新这个主题会很好,因为它由于某种原因仍未解决
我在这里浏览了很多主题,但大多数答案都已过时或标记为不可靠(结果取决于用户是完全滑动还是只滑动一半等)
我访问了 this 话题,但它没有提供任何明确的正确答案。
我试过:
1) 跟踪 viewController 的视图标签 - link - 总是 returns 0
2) 查看 UIPageViewController 方法中的索引变量,viewControllerBeforeViewController
和 viewControllerAfterViewControlle
其结果不可预测,有时会跳过一个索引等
有没有人想出一个好的、可靠的方法来跟踪 UIPageCiewController 索引以利用它(例如打印当前索引)?
我很欣赏 obj-c 和 swift 实现,但 swift 是我正在寻找的那个。
就像@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 {}
就是这样!完美可靠地工作,一点也不滞后!
这是给ObjC
的
ParentViewController
#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
我正在寻找一种可靠的方法来跟踪 UIPageViewController 当前索引。
这个问题众所周知;尽管 viewControllers 被正确显示,但很难跟踪当前索引。
我认为在 SO 社区刷新这个主题会很好,因为它由于某种原因仍未解决
我在这里浏览了很多主题,但大多数答案都已过时或标记为不可靠(结果取决于用户是完全滑动还是只滑动一半等)
我访问了 this 话题,但它没有提供任何明确的正确答案。
我试过:
1) 跟踪 viewController 的视图标签 - link - 总是 returns 0
2) 查看 UIPageViewController 方法中的索引变量,viewControllerBeforeViewController
和 viewControllerAfterViewControlle
其结果不可预测,有时会跳过一个索引等
有没有人想出一个好的、可靠的方法来跟踪 UIPageCiewController 索引以利用它(例如打印当前索引)?
我很欣赏 obj-c 和 swift 实现,但 swift 是我正在寻找的那个。
就像@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 {}
就是这样!完美可靠地工作,一点也不滞后!
这是给ObjC
ParentViewController
#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