这可能看起来像以前问过的问题(PageViewController委托函数调用了两次),但问题是我无法将该解决方案应用于我的问题.
您可能会注意到我正在开发一个日历应用程序并使用UIPageViewController来管理我的年度日历显示.正如您所看到的,我正在使用UIPageViewControllerTransitionStylePageCurl,当用户卷曲页面(向前/向后)时,它们各自的委托被调用两次,这将根据执行的委托给我2年递增或递减.现在我需要找出导致此问题的原因并阻止它执行两次.
我知道在那些给出我的下一页或上一页的委托中返回一个viewController是很重要的,因此我只是刷新了viewController的视图,以便我可以用新数据渲染视图.我也试过其他代表呼吁willTransitionToViewControllers但不会让我在任何地方,因为willTransitionToViewControllers只会viewControllerAfterViewController和viewControllerBeforeViewController后得到执行.
有人帮我理解并解决了这个问题.
- (void)addCalendarViews
{
CGRect frame = CGRectMake(0., 0., self.view.frame.size.width, self.view.frame.size.height);
pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl
navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal
options:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:UIPageViewControllerSpineLocationNone] forKey:UIPageViewControllerOptionSpineLocationKey]];
pageViewController.doubleSided = YES;
pageViewController.delegate = self;
pageViewController.dataSource = self;
YearCalendarViewController *yearController = [[YearCalendarViewController alloc] init];
NSArray *viewControllers = [NSArray arrayWithObject:yearController];
[self.pageViewController setViewControllers:viewControllers
direction:UIPageViewControllerNavigationDirectionReverse
animated:YES
completion:nil];
[self addChildViewController:pageViewController];
[self.view addSubview:pageViewController.view];
[pageViewController didMoveToParentViewController:self];
CGRect pageViewRect = yearController.view.bounds;
self.pageViewController.view.frame = pageViewRect;
viewCalendarMonth = [[SGMonthCalendarView alloc] initWithFrame:frame];
[self.view addSubview:viewCalendarMonth];
arrayCalendars = @[pageViewController.view, viewCalendarMonth];
}
-(UIViewController*)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
NSDate *currentDate = [[SGSharedDate sharedManager] currentDate];
NSDateComponents *currentDateComp = [NSDate returnDateComponentsForDate:currentDate];
self.nextDate = [NSDate dateWithYear:currentDateComp.year+1 month:currentDateComp.month day:currentDateComp.day];
[[SGSharedDate sharedManager] setCurrentDate:nextDate];
{
//I m reloading viewController's view here to display the new set of data for the increamented date.
}
NSLog(@"After Dates====>%@", nextDate);
return viewController;
}
-(UIViewController*)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
NSDate *currentDate = [[SGSharedDate sharedManager] currentDate];
NSDateComponents *currentDateComp = [NSDate returnDateComponentsForDate:currentDate];
nextDate = [NSDate dateWithYear:currentDateComp.year-1 month:currentDateComp.month day:currentDateComp.day];
[[SGSharedDate sharedManager] setCurrentDate:nextDate];
{
//I m reloading viewController's view here to display the new set of data for the decremented date.
}
NSLog(@"Before Dates====>%@", nextDate);
return viewController;
}
Run Code Online (Sandbox Code Playgroud)
该UIPageController往往提前缓存(反面),所以当你从视图控制器刷卡前N,N+1负载但这样做N+2,以便在事件中,你刷卡两次,你的内容已经加载默默.
但是由于你在委托方法中有一个看不见的副作用(递增日期),你会受到这种影响.
我的建议是从你的委托中删除约会副作用,并以某种方式将日期代码绑定到呈现的视图控制器(委托或属性),然后捕获pageController的didFinishAnimating方法.
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed {
if (completed) {
if ([[self.pageViewController.viewControllers firstObject] isKindOfClass:[MyCalenderViewController class]]) {
currentDate = [self workOutCurrentDateForVC:[self.pageViewController.viewControllers firstObject]];
}
}
}
Run Code Online (Sandbox Code Playgroud)
副作用是代码气味.尽量避免.
编辑
我刚刚注意到你正在回收视图控制器并用新的日期点重新加载它.不要这样做.您需要将视图控制器视为图书的单个页面.因此,生成一个新的并将其设置为本月...
简单地作为一个例子......
@interface YearViewController : UIViewController
@property NSDate *focusedYear;
-(instancetype)initWithYear:(NSDate)adate;
@end
@implementation YearViewController
-(instancetype)initWithYear:(NSDate)adate {
self = [super initWithNibName:nil bundle:nil];
if(self) {
self.focusedYear = adate;
....
}
}
@end
Run Code Online (Sandbox Code Playgroud)
因此,在页面控制器委托中,您只需根据前一个日期(以及您正在分页的方向)提供新的"页面"
-(UIViewController*)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
YearViewController *yvc = (YearViewController *)viewController;
NSDate *currentDate = yvc.focusedYear;
NSDateComponents *currentDateComp = [NSDate returnDateComponentsForDate:currentDate];
NSDate *nextDate = [NSDate dateWithYear:currentDateComp.year+1 month:currentDateComp.month day:currentDateComp.day];
YearViewController *freshYVC = [[YearViewController alloc] initWithDate:nextDate];
return freshYVC;
}
Run Code Online (Sandbox Code Playgroud)
关于副作用的评论仍然有效.