1
  1. 在 Xcode 中启动一个新的基于页面的应用程序项目
  2. 运行项目并翻几页
  3. 旋转模拟器或设备
  4. => 页面视图控制器切换回第一页(一月)

如何防止第 4 步。

编辑:这仅在您在模拟器/设备中启动应用程序后第一次旋转时发生。我在我的测试设备上使用带有 iOS 6.0 模拟器和 iOS 6 的最新 Xcode 4.5。当我从博客/等下载一些其他示例代码时,也会发生同样的事情。也许是 iOS 6 错误?

EDIT2:我发现传递给 UIPageViewController 的第一个页面视图在第一次旋转之前不会被释放。这对我来说真的像一个错误。

4

5 回答 5

4

(2014 年更新:如果您从新的 Page View 应用程序模板重新开始,这似乎已在 iOS7 中修复。)

我也遇到过这个错误。它似乎在主视图重新出现后随时启动。我的应用程序中有几个全屏模式,在这些模式消失后会发生相同的行为。

这发生在 XCode 4.5.1 和 iOS6 中——我通过重新下载 XCode 4.4 并将我的应用程序恢复到 iOS5.1 来“修复”这个问题。显然不是一个很好的长期解决方案。我在 Radar 中提交了这个文件,并收到了一个通知,它已经被记录了。

FWIW 我注意到 iBooks 在 iOS6 发布后也有同样的错误,但他们似乎在最近的更新中修复了它。

于 2012-10-24T17:39:08.100 回答
1

这是我设法在我的应用程序中解决此问题的方法。恐怕这是一种 hacky 解决方案,但它是一个古怪的错误。

上下文:我的应用程序是一本日记(称为 Remembary),每一页都是不同日期的日记条目。我有一个名为“AppContext”的单例类,它跟踪各种应用级别的值,例如当前显示的日记条目对象、当前日期等。每天的 dataViewController 也会跟踪它自己的日记条目。

最棘手的部分是找到一个上下文,我可以在其中发现应用程序显示了错误的页面。原来这是在 [RootViewController viewDidLayoutSubviews] 中,所以我在该方法中添加了以下内容:

// get the currently displaying page
DataViewController *currentPage = self.pageViewController.viewControllers[0];
// check if we're showing the wrong page
if ([currentPage myEntry] != [AppContext getCurrentEntry]) {        
    // jump to the proper page (the delay is needed to ensure that the rotation has fully completed)
    [self performSelector:@selector(forceJumpToDate:) 
               withObject:[AppContext getCurrentEntryDate] 
               afterDelay:0.5];
}

下面是 forceJumpToDate 函数,它基本上根据当前日期获取一个新页面,并告诉 pageViewController 在没有动画的情况下跳转到它:

- (void) forceJumpToDate:(NSDate *)targetDate {
    DataViewController *targetPage = [self.modelController viewControllerForDate:targetDate 
                                                                      storyboard:self.storyboard];
    NSArray *viewControllers = [NSArray arrayWithObject:targetPage];
    [self.pageViewController setViewControllers:viewControllers 
                                      direction:UIPageViewControllerNavigationDirectionForward 
                                       animated:NO 
                                     completion:NULL];
}

当新页面被强制就位时,用户可能会注意到屏幕上出现短暂的打嗝,但这只有在他们会得到错误页面的情况下才会发生,所以它仍然是一个改进。

这严重干扰了我将应用程序升级到 iOS6 的能力,所以我很高兴我终于弄明白了。

于 2012-10-25T17:56:27.303 回答
1

这是我的解决方案:


//  RootViewController.m

#import "RootViewController.h"

#import "ModelController.h"

#import "DataViewController.h"

@interface RootViewController ()
@property (readonly, strong, nonatomic) ModelController *modelController;

//added
@property (strong, nonatomic) DataViewController *currentViewController;
@end

@implementation RootViewController

@synthesize modelController = _modelController;

//added
@synthesize currentViewController = _currentViewController;

- (void)viewDidLoad
{
    [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
    // Configure the page view controller and add it as a child view controller.
    self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
    self.pageViewController.delegate = self;

    DataViewController *startingViewController = [self.modelController viewControllerAtIndex:0 storyboard:self.storyboard];
    NSArray *viewControllers = @[startingViewController];
    [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:NULL];

    self.pageViewController.dataSource = self.modelController;

    [self addChildViewController:self.pageViewController];
    [self.view addSubview:self.pageViewController.view];

    // Set the page view controller's bounds using an inset rect so that self's view is visible around the edges of the pages.
    CGRect pageViewRect = self.view.bounds;
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
        pageViewRect = CGRectInset(pageViewRect, 40.0, 40.0);
    }
    self.pageViewController.view.frame = pageViewRect;

    [self.pageViewController didMoveToParentViewController:self];

    // Add the page view controller's gesture recognizers to the book view controller's view so that the gestures are started more easily.
    self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;

    //added
    self.currentViewController = self.pageViewController.viewControllers[0];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (ModelController *)modelController
{
     // Return the model controller object, creating it if necessary.
     // In more complex implementations, the model controller may be passed to the view controller.
    if (!_modelController) {
        _modelController = [[ModelController alloc] init];
    }
    return _modelController;
}

#pragma mark - UIPageViewController delegate methods

/*
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{

}
 */


//added
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration

{
    self.currentViewController = self.pageViewController.viewControllers[0];

}

- (DataViewController *)currentViewController
{
    if (!_currentViewController) _currentViewController = [[DataViewController alloc] init];
    return _currentViewController;
}



- (UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation
{
    if (UIInterfaceOrientationIsPortrait(orientation) || ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)) {
        // In portrait orientation or on iPhone: Set the spine position to "min" and the page view controller's view controllers array to contain just one view controller. Setting the spine position to 'UIPageViewControllerSpineLocationMid' in landscape orientation sets the doubleSided property to YES, so set it to NO here.



        //deleted: UIViewController *currentViewController = self.pageViewController.viewControllers[0];
        //changed to self.currentViewController
        NSArray *viewControllers = @[self.currentViewController];
        [self.pageViewController setViewControllers:viewControllers
                                          direction:UIPageViewControllerNavigationDirectionForward
                                          animated:YES
                                          completion:NULL];

        self.pageViewController.doubleSided = NO;
        return UIPageViewControllerSpineLocationMin;
    }

    // In landscape orientation: Set set the spine location to "mid" and the page view controller's view controllers array to contain two view controllers. If the current page is even, set it to contain the current and next view controllers; if it is odd, set the array to contain the previous and current view controllers.
   // deleted:  DataViewController *currentViewController = self.pageViewController.viewControllers[0];
   //deleted: NSArray *viewControllers = nil;
    //added
     NSArray *viewControllers = @[self.currentViewController];

   //changed currentViewController to self.currentViewController
    NSUInteger indexOfCurrentViewController = [self.modelController indexOfViewController:self.currentViewController];

    if (indexOfCurrentViewController == 0 || indexOfCurrentViewController % 2 == 0) {
        UIViewController *nextViewController = [self.modelController pageViewController:self.pageViewController viewControllerAfterViewController:self.currentViewController];
        viewControllers = @[self.currentViewController, nextViewController];
    } else {
        UIViewController *previousViewController = [self.modelController pageViewController:self.pageViewController viewControllerBeforeViewController:self.currentViewController];
        viewControllers = @[previousViewController, self.currentViewController];
    }
    [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL];


    return UIPageViewControllerSpineLocationMid;
}

@end
于 2013-06-06T18:49:02.087 回答
0

今天我发现在我的应用程序中我可以使用以下内容来删除错误(但我不知道为什么)。

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
        ...
         self.pageViewController.view.hidden = YES;
    }

-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
        self.pageViewController.view.hidden = NO;
    }
于 2013-03-12T16:45:38.477 回答
0

What is it you want to prevent? Do you want to prevent rotation? If that is what you want, modify the shouldAutorotateToInterfaceOrientation return value in the RootViewController.m implementation file.

When I did this, the App was able to keep the same page (month) even after rotating the device. I used the simulator and tried on both iPhone and iPad. On the iPad, in landscape mode, it showed two months at a time, but then when rotated back to portrait, still kept the first of the two months that was displayed. This was when I incremented to June. I used the default project without changing a line of code.

于 2012-09-25T22:28:52.297 回答