在 UIViewController 中嵌入 UIPageViewController 停止分页
Embedding a UIPageViewController in a UIViewController stops paging
我正在处理模态呈现的灯箱,但在将 UIPageViewController
嵌入父视图控制器时遇到了问题(以允许 "floating" 未分页的元素)。
以下是包含 UIViewController
的来源。它的 Xib 包含一个 UIButton
和一个 UIView
以及一个名为 workingArea
.
的出口
视图数组 (vc
) 填充了一个测试 class,将纯色图像放在视图的中心。
@interface LightboxContainerViewController ()
@property (nonatomic) NSArray *vcs;
@end
@implementation LightboxContainerViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
UIPageViewController *lb = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
lb.dataSource = self;
self.vcs = @[
[[LightboxViewController alloc] initWithNibName:@"LightboxViewController" bundle:nil andImage:[UIImage imageWithColor:[UIColor redColor]]],
[[LightboxViewController alloc] initWithNibName:@"LightboxViewController" bundle:nil andImage:[UIImage imageWithColor:[UIColor greenColor]]],
[[LightboxViewController alloc] initWithNibName:@"LightboxViewController" bundle:nil andImage:[UIImage imageWithColor:[UIColor blueColor]]]
];
[lb setViewControllers:@[self.vcs[0]]
direction:UIPageViewControllerNavigationDirectionForward
animated:NO completion:nil];
lb.view.frame = self.workingArea.bounds;
[self.workingArea addSubview:lb.view];
}
-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController
viewControllerBeforeViewController:(UIViewController *)viewController
{
NSUInteger currentIndex = [self.vcs indexOfObject:viewController];
if(currentIndex == 0){
return nil;
}
return [self.vcs objectAtIndex:--currentIndex];
}
-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController
viewControllerAfterViewController:(UIViewController *)viewController
{
NSUInteger currentIndex = [self.vcs indexOfObject:viewController];
if(currentIndex == self.vcs.count - 1){
return nil;
}
// Output selected VC
return [self.vcs objectAtIndex:++currentIndex];
}
-(NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController
{
return self.vcs.count;
}
-(NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController
{
return 0;
}
#pragma Modal view management
- (void) presentModal {
[[[[[UIApplication sharedApplication] delegate] window] rootViewController] presentViewController:self animated:YES completion:nil];
[UIView animateWithDuration:0.3 animations:^{
[[UIApplication sharedApplication] setStatusBarHidden:YES];
}];
}
- (void) dismissModal {
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
[UIView animateWithDuration:0.3 animations:^{
[[UIApplication sharedApplication] setStatusBarHidden:NO];
}];
}
#pragma mark UI interaction
- (IBAction)closePressed:(id)sender {
[self dismissModal];
}
#pragma mark UIPageViewControllerDatasource
-(UIViewController *)viewControllerAtIndex:(NSUInteger)index
{
return self.vcs[index];
}
@end
三个中的第一个 UIViewController
显示正常,滚动指示器中有三个点,但我无法在页面之间滑动。
我设置了断点,viewControllerBeforeViewController
/viewControllerAfterViewController
从未被调用,尽管 presentationIndexForPageViewController
被调用。
当数据源方法直接包含在 UIPageViewController
中时,这段代码似乎工作正常,只有当嵌入到父 UIViewController
中时,它才会像这样卡住。
lb
在alloc
之后发布。所以它什么也做不了
UIPageViewController *lb = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
您应该在 .h 或 .m 文件中创建一个 var,例如:
@interface LightboxContainerViewController ()
{
UIPageViewController *lb
}
@property (nonatomic) NSArray *vcs;
@end
然后
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
lb = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
// .....
}
为了完整起见,这是我最终做出的更改以及原因(新行标记为 NEW):
- (void)viewDidLoad {
// ...
UIPageViewController *lb = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
lb.dataSource = self;
// Populate self.vs here
// NEW: Added this line to ensure we retain a reference to lb
[self addChildViewController:lb];
[lb setViewControllers:@[self.vcs[0]]
direction:UIPageViewControllerNavigationDirectionForward
animated:NO completion:nil];
// Set page view controller's view's frame to match host view's frame
lb.view.frame = self.workingArea.bounds;
// NEW: Added this line to notify lb of what's happening
[lb didMoveToParentViewController:self];
[self.workingArea addSubview:lb.view];
}
这与用于容器视图的模式相同,并确保我们保留对 UIPageViewController
的引用,以便在交互时可以找到委托。
加载后 UIPageViewController
我不需要做任何额外的工作,所以这足以满足我的目的。
我正在处理模态呈现的灯箱,但在将 UIPageViewController
嵌入父视图控制器时遇到了问题(以允许 "floating" 未分页的元素)。
以下是包含 UIViewController
的来源。它的 Xib 包含一个 UIButton
和一个 UIView
以及一个名为 workingArea
.
视图数组 (vc
) 填充了一个测试 class,将纯色图像放在视图的中心。
@interface LightboxContainerViewController ()
@property (nonatomic) NSArray *vcs;
@end
@implementation LightboxContainerViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
UIPageViewController *lb = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
lb.dataSource = self;
self.vcs = @[
[[LightboxViewController alloc] initWithNibName:@"LightboxViewController" bundle:nil andImage:[UIImage imageWithColor:[UIColor redColor]]],
[[LightboxViewController alloc] initWithNibName:@"LightboxViewController" bundle:nil andImage:[UIImage imageWithColor:[UIColor greenColor]]],
[[LightboxViewController alloc] initWithNibName:@"LightboxViewController" bundle:nil andImage:[UIImage imageWithColor:[UIColor blueColor]]]
];
[lb setViewControllers:@[self.vcs[0]]
direction:UIPageViewControllerNavigationDirectionForward
animated:NO completion:nil];
lb.view.frame = self.workingArea.bounds;
[self.workingArea addSubview:lb.view];
}
-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController
viewControllerBeforeViewController:(UIViewController *)viewController
{
NSUInteger currentIndex = [self.vcs indexOfObject:viewController];
if(currentIndex == 0){
return nil;
}
return [self.vcs objectAtIndex:--currentIndex];
}
-(UIViewController *)pageViewController:(UIPageViewController *)pageViewController
viewControllerAfterViewController:(UIViewController *)viewController
{
NSUInteger currentIndex = [self.vcs indexOfObject:viewController];
if(currentIndex == self.vcs.count - 1){
return nil;
}
// Output selected VC
return [self.vcs objectAtIndex:++currentIndex];
}
-(NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController
{
return self.vcs.count;
}
-(NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController
{
return 0;
}
#pragma Modal view management
- (void) presentModal {
[[[[[UIApplication sharedApplication] delegate] window] rootViewController] presentViewController:self animated:YES completion:nil];
[UIView animateWithDuration:0.3 animations:^{
[[UIApplication sharedApplication] setStatusBarHidden:YES];
}];
}
- (void) dismissModal {
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
[UIView animateWithDuration:0.3 animations:^{
[[UIApplication sharedApplication] setStatusBarHidden:NO];
}];
}
#pragma mark UI interaction
- (IBAction)closePressed:(id)sender {
[self dismissModal];
}
#pragma mark UIPageViewControllerDatasource
-(UIViewController *)viewControllerAtIndex:(NSUInteger)index
{
return self.vcs[index];
}
@end
三个中的第一个 UIViewController
显示正常,滚动指示器中有三个点,但我无法在页面之间滑动。
我设置了断点,viewControllerBeforeViewController
/viewControllerAfterViewController
从未被调用,尽管 presentationIndexForPageViewController
被调用。
当数据源方法直接包含在 UIPageViewController
中时,这段代码似乎工作正常,只有当嵌入到父 UIViewController
中时,它才会像这样卡住。
lb
在alloc
之后发布。所以它什么也做不了
UIPageViewController *lb = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
您应该在 .h 或 .m 文件中创建一个 var,例如:
@interface LightboxContainerViewController ()
{
UIPageViewController *lb
}
@property (nonatomic) NSArray *vcs;
@end
然后
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
lb = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
// .....
}
为了完整起见,这是我最终做出的更改以及原因(新行标记为 NEW):
- (void)viewDidLoad {
// ...
UIPageViewController *lb = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
lb.dataSource = self;
// Populate self.vs here
// NEW: Added this line to ensure we retain a reference to lb
[self addChildViewController:lb];
[lb setViewControllers:@[self.vcs[0]]
direction:UIPageViewControllerNavigationDirectionForward
animated:NO completion:nil];
// Set page view controller's view's frame to match host view's frame
lb.view.frame = self.workingArea.bounds;
// NEW: Added this line to notify lb of what's happening
[lb didMoveToParentViewController:self];
[self.workingArea addSubview:lb.view];
}
这与用于容器视图的模式相同,并确保我们保留对 UIPageViewController
的引用,以便在交互时可以找到委托。
加载后 UIPageViewController
我不需要做任何额外的工作,所以这足以满足我的目的。