我实际上正在制作一个旋转木马。我的目标是使它成为通用的,这意味着我希望它能够接收一个控制器数组,并且只创建旋转木马(计数UIPageViewController将以与数组相同的顺序显示控制器)。
我到目前为止构建的是接收控制器数组的控制器,以及构建基本屏幕的通用控制器。
管理数组中页面的控制器是:
BSRGenericOnboarding
(H)
#import <UIKit/UIKit.h>
@class BaseViewController;
#pragma mark - DELEGATE
// Future Use
@protocol BSRGenericOnboardingDelegate <NSObject>
@required
@optional
@end
#pragma mark - DATASOURCE
// Future Use
@protocol BSRGenericOnboardingDataSource <NSObject>
@required
@optional
@end
#pragma mark - INTERFACE
@interface BSRGenericOnboarding : UIViewController <UIPageViewControllerDelegate ,UIPageViewControllerDataSource>
@property (nonatomic, weak) id<BSRGenericOnboardingDelegate> delegate;
@property (nonatomic, strong) NSArray *pantallas;// save screens
// INIT HERE
- (instancetype)initWithArrayOfControllers:(NSArray *)arrayOfControllers
andCallerController:(BaseViewController *)callerController;
// Close the onboarding
- (void)dismissOnboarding;
@end
(M)
#import "BSRGenericOnboarding.h"
#import "BSRGenericOnboardingScreenViewController.h"
#import "BaseViewController.h"
#import "BSROnboardingCarouselButton.h"
#import "Constants.h"// Import screen measures and constants
@interface BSRGenericOnboarding ()
@property (nonatomic, weak) BaseViewController *BVC;// contains the caller of this object
@property (nonatomic, strong) UIPageViewController *UIPageCV;
@end
@implementation BSRGenericOnboarding
#pragma mark - init
// INIT
- (instancetype)initWithArrayOfControllers:(NSArray *)arrayOfControllers
andCallerController:(BaseViewController *)callerController {
self = [super init];
if (self) {
self.pantallas = [arrayOfControllers copy]; // getting screens!
self.BVC = callerController;
}
return self;
}
#pragma mark - view Lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
// add a self reference to screens
[self addSelfToScreens];
// Init UIPageViewCotroller
self.UIPageCV = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll
navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal
options:nil];
self.view.backgroundColor = [UIColor clearColor];
self.UIPageCV.view.backgroundColor = [UIColor clearColor];
self.UIPageCV.delegate = self;
self.UIPageCV.dataSource = self;
[[self.UIPageCV view] setFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
[self.UIPageCV setViewControllers:@[self.pantallas[0]]
direction:UIPageViewControllerNavigationDirectionForward
animated:NO
completion:nil];
[self addChildViewController:self.UIPageCV];
[self.view addSubview:self.UIPageCV.view];
[self.UIPageCV didMoveToParentViewController:self];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - UIPageViewControllerDelegate
- (void)pageViewController:(UIPageViewController *)pageViewController
willTransitionToViewControllers:(NSArray<UIViewController *> *)pendingViewControllers {
}
#pragma mark - UIPageViewControllerDataSource
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
viewControllerAfterViewController:(UIViewController *)viewController {
for(int i=0;i<self.pantallas.count ;i++)
{
if(viewController == [self.pantallas objectAtIndex:i])
{
if(i+1 < self.pantallas.count)
{
return [self.pantallas objectAtIndex:i+1];
}
}
}
return nil;
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
viewControllerBeforeViewController:(UIViewController *)viewController {
for(int i=0;i<self.pantallas.count ;i++)
{
if(viewController == [self.pantallas objectAtIndex:i])
{
if(i-1 >= 0)
{
return [self.pantallas objectAtIndex:i-1];
}
}
}
return nil;
}
#pragma mark - UIPageViewController Utils
// Cierra el onboarding
- (void)dismissOnboarding {
[self dismissViewControllerAnimated:NO completion:nil];
}
- (void)addSelfToScreens {
for (BSRGenericOnboardingScreenViewController *screen in self.pantallas) {
screen.onboardingUIPageVC = self;
}
}
@end
作为所有屏幕基础的控制器是:
BSRGenericOnboardingScreenViewController
(H)
#define INDEXDOTHIGH 15 //index button high
#define INDEXDOTWIDTH 15 //index button width
#define ESPACIADO 4 //index buttons spacing
#import <UIKit/UIKit.h>
#import "BSRGenericOnboarding.h"
#import "BSROnboardingCarouselBar.h"
@interface BSRGenericOnboardingScreenViewController : UIViewController
//contains the reference to the BSRGenericOnboarding
@property (nonatomic, weak) BSRGenericOnboarding *onboardingUIPageVC;
//contains the reference of the object caller of BSRGenericOnboarding
@property (nonatomic, weak) BaseViewController *BVC;
@property (nonatomic, strong) BSROnboardingCarouselBar *buttonsBar;
//Hide buttons bar
- (void)hideCasrousel;
//Show buttons bar
- (void)unhideCasrousel;
@end
(M)
#import "BSRGenericOnboarding.h"
#import "BSRGenericOnboardingScreenViewController.h"
#import "BSROnboardingCarouselBar.h"
#import "Constants.h" // Constantes de tamano de pantalla
@interface BSRGenericOnboardingScreenViewController ()
@property (nonatomic, strong) UIView *backScreen;// black screen for behind
@end
@implementation BSRGenericOnboardingScreenViewController
#pragma mark - View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[[[UIApplication sharedApplication] keyWindow] addSubview:self.view];
[self setCarouselBar];
self.backScreen = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
self.backScreen.alpha = 0.9;
self.backScreen.backgroundColor = [UIColor blackColor];
[self.view addSubview:self.backScreen];
[self.view sendSubviewToBack:self.backScreen];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Index Carousel Dots
//Esconde el carousel
- (void)hideCasrousel {
self.buttonsBar.hidden = YES;
}
// Muesta el carousel
- (void)unhideCasrousel {
self.buttonsBar.hidden = NO;
}
- (void)setCarouselBar {
CGFloat buttonsBarX = center(SCREEN_WIDTH, ((INDEXDOTWIDTH * [self.onboardingUIPageVC.pantallas count]) + (ESPACIADO * ([self.onboardingUIPageVC.pantallas count] - 1))));
CGFloat buttonsBarY = SCREEN_HEIGHT - INDEXDOTHIGH - 15;
CGFloat buttonsBarW = INDEXDOTWIDTH;
CGFloat buttonsBarH = INDEXDOTHIGH;
self.buttonsBar = [[BSROnboardingCarouselBar alloc] initWithFrame:CGRectMake(buttonsBarX, buttonsBarY, buttonsBarW, buttonsBarH) numberOfPages:[self.onboardingUIPageVC.pantallas count] withEspaciado:ESPACIADO];
[self.view addSubview:self.buttonsBar];
}
@end
这就是我称之为onboarding的方式:
- (void)createOnboarding {
// Onboarding Screens
pag1ViewController *vc1 = [[pag1ViewController alloc] init];
pag2ViewController *vc2 = [[pag2ViewController alloc] init];
BSRComodinesSuperClubOnboardingScreen1 *vc3 = [[BSRComodinesSuperClubOnboardingScreen1 alloc] init];
self.vc = [[BSRGenericOnboarding alloc] initWithArrayOfControllers:[[NSArray alloc] initWithObjects:vc1, vc2, vc3,nil]
andCallerController:self];
self.vc.modalPresentationStyle = UIModalPresentationOverCurrentContext;
[self presentViewController:self.vc animated:NO completion:nil];
}
问题在于,当我滚动旋转木马的第一页时,有时会在所有视图前面随机地显示下一页(foward页面),如照片所示:
The green background is the first view of the carousel, the yellow one is the following
我搜索了几天,我无法通过自己解决它,这是我唯一可以搞清楚的事情,有时当方法pageViewController:viewControllerAfterViewController:和pageViewController:viewControllerBeforeViewController:被调用时,它们带来了前瞻性查看旋转木马的顶部,同时显示2个视图,如照片所示。
我想知道如何解决这个问题,如果有更简单的方法可以解决这个问题。
非常感谢您的阅读!