ios UIPageViewController:返回当前可见视图
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8400870/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
UIPageViewController: return the current visible view
提问by Jan
How do you know what is the current page/view displayed inside an UIPageViewController
?
你怎么知道当前页面/视图显示在UIPageViewController
.
I have overridden the viewDidAppear
method of my child views, so that they send an id to the parent view in their viewDidAppear
method.
我已经覆盖了viewDidAppear
我的子视图的方法,以便他们在他们的viewDidAppear
方法中向父视图发送一个 id 。
However, the problem is this: i cannot reliably use that id as id for the displayed page. because if the user turns the page but halfway through decides to stop the turning and put the page back, viewDidAppear
will already have been called. (the view is visible behind the curled page).
但是,问题是:我不能可靠地使用该 ID 作为显示页面的 ID。因为如果用户翻页但中途决定停止翻页并将页面放回去,viewDidAppear
将已经被调用。(视图在卷曲页面后面可见)。
Maybe i should only switch to a new id if the current view disappears. But I wonder if there is not a more simple way to return the view that is currently visible?
也许我应该只在当前视图消失时切换到新的 id。但是我想知道是否没有更简单的方法来返回当前可见的视图?
回答by Ole Begemann
You should manually keep track of the current page. The delegate method pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted:
will tell you when to update that variable. The last argument of the method transitionCompleted:
can tell you whether a user completed a page turn transition or not.
您应该手动跟踪当前页面。委托方法pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted:
会告诉您何时更新该变量。该方法的最后一个参数transitionCompleted:
可以告诉您用户是否完成了翻页转换。
回答by Eddy Borja
As of iOS 6 I've found that the viewControllers
property of UIPageViewController constantly updates so that it will always hold the one view controller that represents the current page, and nothing else. Thus, you can access the current page by calling viewControllers[0]
(Assuming you only show one view controller at a time).
从 iOS 6 开始,我发现viewControllers
UIPageViewController的属性会不断更新,以便它始终保留代表当前页面的一个视图控制器,而没有其他内容。因此,您可以通过调用来访问当前页面viewControllers[0]
(假设您一次只显示一个视图控制器)。
The viewController array only updates once the page "locks" into place, so if a user decides to partially reveal the next page it doesn't become the "current" page unless they complete the transition.
viewController 数组仅在页面“锁定”到位后更新,因此如果用户决定部分显示下一页,除非他们完成转换,否则它不会成为“当前”页面。
If you want to keep track of the "page numbers" assign your view controllers an index value as you create them through the UIPageViewController datasource methods.
如果您想跟踪“页码”,则在您通过 UIPageViewController 数据源方法创建它们时,为您的视图控制器分配一个索引值。
So for example:
例如:
-(void)autoAdvance
{
UIViewController *currentVC = self.viewControllers[0];
NSUInteger currentIndex = [myViewControllers indexOfObject:currentVC];
if ( currentIndex >= (myViewControllers.count-1) ) return;
[self setViewControllers:@[myViewControllers[ currentIndex+1 ]]
direction:UIPageViewControllerNavigationDirectionForward
animated:YES
completion:nil];
}
-(NSInteger)presentationIndexForPageViewController:
(UIPageViewController *)pageViewController
{
// return 0;
UIViewController *currentVC = self.viewControllers[0];
NSUInteger currentIndex = [myViewControllers indexOfObject:currentVC];
return currentIndex;
}
But note the commentsthat this is unreliable.
但请注意,这是不可靠的评论。
回答by Victor
Unfortunately, all above methods didn't help me. Nevertheless, I have found the solution by using tags. May be it's not the best, but it works and hope it helps someone:
不幸的是,上述所有方法都没有帮助我。尽管如此,我还是通过使用标签找到了解决方案。可能它不是最好的,但它有效并希望它可以帮助某人:
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
if (completed) {
int currentIndex = ((UIViewController *)self.pageViewController.viewControllers.firstObject).view.tag;
self.pageControl.currentPage = currentIndex;
}
}
In Swift:(thanks to @Jessy)
在 Swift 中:(感谢@Jessy)
func pageViewController(pageViewController: UIPageViewController,
didFinishAnimating finished: Bool,
previousViewControllers: [UIViewController],
transitionCompleted completed: Bool)
{
guard completed else { return }
self.pageControl.currentPage = pageViewController.viewControllers!.first!.view.tag
}
Example:gist
示例:要点
回答by Corey Floyd
Building on Ole's Answer…
基于 Ole 的回答……
This is how I implemented the 4 methods to track the current page and update the page indicator to the correct index:
这就是我如何实现 4 种方法来跟踪当前页面并将页面指示器更新为正确的索引:
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController{
return (NSInteger)[self.model count];
}
- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController{
return (NSInteger)self.currentIndex;
}
- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers{
SJJeanViewController* controller = [pendingViewControllers firstObject];
self.nextIndex = [self indexOfViewController:controller];
}
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed{
if(completed){
self.currentIndex = self.nextIndex;
}
self.nextIndex = 0;
}
回答by sirvine
The solution below worked for me.
下面的解决方案对我有用。
Apple could avoid a lot of hassle by making the native UIPageViewController scroll view pagination more configurable. I had to resort to overlaying a new UIView and UIPageControl just because the native UIPageViewController pagination won't support a transparent background or repositioning within the view frame.
Apple 可以通过使原生 UIPageViewController 滚动视图分页更具可配置性来避免很多麻烦。我不得不求助于覆盖一个新的 UIView 和 UIPageControl 只是因为本机 UIPageViewController 分页不支持透明背景或在视图框架内重新定位。
- (void)pageViewController:(UIPageViewController *)pvc didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
if (!completed)
{
return;
}
NSUInteger currentIndex = [[self.pageViewController.viewControllers lastObject] index];
self.pageControl.currentPage = currentIndex;
}
回答by Nikola Milicevic
Swift 4
斯威夫特 4
No unnecessary code. 3 ways of doing it. Using UIPageViewControllerDelegatemethod.
没有不必要的代码。3 种方法。使用UIPageViewControllerDelegate方法。
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
guard completed else { return }
// using content viewcontroller's index
guard let index = (pageViewController.viewControllers?.first as? ContentViewController)?.index else { return }
// using viewcontroller's view tag
guard let index = pageViewController.viewControllers?.first?.view.tag else { return }
// switch on viewcontroller
guard let vc = pageViewController.viewControllers?.first else { return }
let index: Int
switch vc {
case is FirstViewController:
index = 0
case is SecondViewController:
index = 1
default:
index = 2
}
}
回答by Wahib Ul Haq
I am keeping track of the page index by using a small function and specifying pageIndex as static NSInteger.
我通过使用一个小函数并将 pageIndex 指定为静态 NSInteger 来跟踪页面索引。
-(void) setPageIndex
{
DataViewController *theCurrentViewController = [self.pageViewController.viewControllers objectAtIndex:0];
pageIndex = [self.modelController indexOfViewController:theCurrentViewController];
}
and calling [self setPageIndex];
inside the function specified by Ole and also after detecting the change in orientation.
并[self setPageIndex];
在 Ole 指定的函数内部以及在检测到方向变化后调用。
回答by Basit Ali
I first used Corey's solution but it wasn't working on iOS5 then ended up using,
我首先使用了 Corey 的解决方案,但它在 iOS5 上不起作用,然后最终使用了,
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed{
if(completed) {
_currentViewController = [pageViewController.viewControllers lastObject];
}
}
It tried switching through different pages and it works well for now.
它尝试切换不同的页面,目前效果很好。
回答by 0yeoj
Unfortunately nothing above works for me.
不幸的是,以上没有对我有用。
I have two view controllers and when I slightly (around 20px) scroll the last view backwards it triggers the delegate:
我有两个视图控制器,当我稍微(大约 20 像素)向后滚动最后一个视图时,它会触发委托:
pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted:
pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted:
and saying that the current page (index) is 0
which is wrong.
并说当前页面(索引)0
是错误的。
Using delegate inside child viewController something like:
在子 viewController 中使用委托类似于:
- (void)ViewController:(id)VC didShowWithIndex:(long)page;
// and a property
@property (nonatomic) NSInteger index;
that is triggered inside viewDidAppear
like:
在内部触发,viewDidAppear
如:
- (void)viewDidAppear:(BOOL)animated
{
...
[self.delegate ViewController:self didShowWithIndex:self.index];
}
Worked for me.
为我工作。
回答by lguerra10
This works for me reliably
这对我有用
I have a custom UIPageController. This pageController.currentPage is updated from the displayed UIViewController in the viewWillAppear
我有一个自定义 UIPageController。这个 pageController.currentPage 是从 viewWillAppear 中显示的 UIViewController 更新的
var delegate: PageViewControllerUpdateCurrentPageNumberDelegate?
init(delegate: PageViewControllerUpdateCurrentPageNumberDelegate ){
self.delegate = delegate
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewWillAppear(animated: Bool) {
if delegate != nil {
self.delegate!.upateCurrentPageNumber(0) //(0) is the pageNumber corresponding to the displayed controller
}
}
//In the pageViewController
protocol PageViewControllerUpdateCurrentPageNumberDelegate {
func upateCurrentPageNumber(currentPageIndex: Int)
}
create the view display controllers initializing with the delegate
orderedViewControllers = {
return [
IntroductionFirstPageViewController(delegate: self),
IntroductionSecondPageViewController(delegate: self),
IntroductionThirdPageViewController(delegate: self)
]
}()
the function implementing the protocol
func upateCurrentPageNumber(currentPageIndex: Int){
pageControl.currentPage = currentPageIndex
}