Неуравновешенные вызовы для начала / конца перехода на внешний вид UIPageViewcontroller swift [duplicate]

Не совсем var_dump, но полезно: http://dbug.ospinto.com/

15
задан Nayan 6 November 2012 в 12:25
поделиться

10 ответов

Решено следующее: 1- Объявить флаг, указывающий, что анимация завершена или нет:

BOOL pageAnimationFinished;

2- Установите для этого флага значение true в viewDidLoad:

pageAnimationFinished = YES;

3- Отключить tapGesture для pageViewController и назначить 'self' делегату panGestureRecognizer:

for (UIGestureRecognizer * gesRecog in self.pageViewController.gestureRecognizers)
{
    if ([gesRecog isKindOfClass:[UITapGestureRecognizer class]])
        gesRecog.enabled = NO;
    else if ([gesRecog isKindOfClass:[UIPanGestureRecognizer class]])
        gesRecog.delegate = self;
}

4- Разрешить / Запретить panGestureRecognizer через следующий метод делегирования распознавателя жестов:

-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
    if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && ([gestureRecognizer.view isEqual:self.view] || [gestureRecognizer.view isEqual:self.pageViewController.view]))
    {
        UIPanGestureRecognizer * panGes = (UIPanGestureRecognizer *)gestureRecognizer;
        if(!pageAnimationFinished || (currentPage < minimumPage && [panGes velocityInView:self.view].x < 0) || (currentPage > maximumPage && [panGes velocityInView:self.view].x > 0))
            return NO;
        pageAnimationFinished = NO;
    }
    return YES;
}

5- Добавьте следующий метод делегатаViewController:

- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
    pageAnimationFinished = YES;
}
9
ответ дан Basem Saadawy 25 August 2018 в 12:46
поделиться

Вышеуказанные ответы были правильными, но я считаю более сложными, чем это необходимо, и кулинарная книга полезна. Итак, вот что, кажется, работает для меня:

В контроллере представления, который устанавливает и вызывает pageViewController, объявляет:

@property (assign)              BOOL pageIsAnimating;

и в viewDidLoad:

    pageIsAnimating = NO;

добавьте это:

- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers {
    pageIsAnimating = YES;
}

и добавьте пару строк:

- (void)pageViewController:(UIPageViewController *)pageViewController
    didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers
   transitionCompleted:(BOOL)completed {
    if (completed || finished)   // Turn is either finished or aborted
        pageIsAnimating = NO;
    ...
}

Жесты подавляются путем отказа от предоставления информации о контроллере просмотра:

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
   viewControllerAfterViewController:(UIViewController *)viewController {
    if (pageIsAnimating)
        return nil;
    ...
    return after;
}

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
  viewControllerBeforeViewController:(UIViewController *)viewController {
    if (pageIsAnimating)
        return nil;
    ...
    return before;
}

Ох, а изменения ориентации сбросят флаг:

- (UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController
               spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation {
    pageIsAnimating = NO;
    ...
}
27
ответ дан Bill Cheswick 25 August 2018 в 12:46
поделиться

Я попытаюсь проигнорировать жест в UIPageViewControllers во время перехода.

-2
ответ дан Basem Saadawy 25 August 2018 в 12:46
поделиться

Мое решение в быстром, простом и рабочем:

  1. Установите делегат showviewview для вашего класса
  2. Добавьте код ниже
    extension MyPageVC: UIPageViewControllerDelegate {
    
        func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
            self.view.isUserInteractionEnabled = false
        }
    
        func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
            self.view.isUserInteractionEnabled = true
        }
    }
    
2
ответ дан buxik 25 August 2018 в 12:46
поделиться

Хороший ответ из Basem Saadawy, но он имеет некоторый дефект.

На самом деле, вызов делегатаRecognizerShouldBegin: может быть вызван без дальнейшей анимации. Это возможно, если вы начинаете свой жест движением вертикального пальца, а его горизонтальное смещение недостаточно для запуска анимации (но этого достаточно, чтобы запустить gestureRecognizerShouldBegin: ). Таким образом, наша переменная pageAnimationFinished будет установлена ​​в NO без реальной анимации. Поэтому pageViewController: didFinishAnimating: никогда не будет вызываться, и вы можете заблокировать текущую страницу без возможности ее изменения.

Вот почему лучше назначить NO этой переменной - это метод действия распознавателя жестов с экзаменом (нас интересует только горизонтальное направление).

Итак, последние шаги:

1) Объявить переменную экземпляра (флаг):

BOOL pageAnimationFinished;

2) Задайте свое начальное значение

- (void)viewDidLoad
{
    [super viewDidLoad];
    ...
    pageAnimationFinished = YES;
}

3) Назначьте делегат и пользовательское действие распознающим жестам

for (UIGestureRecognizer * gesRecog in self.pageViewController.gestureRecognizers)
{
    if ([gesRecog isKindOfClass:[UIPanGestureRecognizer class]])
    {
        gesRecog.delegate = self;
        [gr addTarget:self action:@selector(handlePan:)];
    }
}

3 ') Анимация действительно начинается, когда перевод жестов больше в горизонтальном направлении, и палец движется горизонтально в одно мгновение. Я предполагаю, что одна и та же логика используется во внутреннем распознавателе, назначаемом UIPageViewController .

- (void) handlePan:(UIPanGestureRecognizer *)gestureRecognizer
{
    if (pageAnimationFinished && gestureRecognizer.state == UIGestureRecognizerStateChanged)
    {
        CGPoint vel = [gestureRecognizer velocityInView:self.view];
        CGPoint tr = [gestureRecognizer translationInView:self.view];
        if (ABS(vel.x) > ABS(vel.y) && ABS(tr.x) > ABS(tr.y))
            pageAnimationFinished = NO; // correct place
    }
}

4) Запрет жестов, если анимация еще не закончена.

-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
    if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && ([gestureRecognizer.view isEqual:self.view] || [gestureRecognizer.view isEqual:self.pageViewController.view]))
    {
        UIPanGestureRecognizer * panGes = (UIPanGestureRecognizer *)gestureRecognizer;
        if(!pageAnimationFinished || (currentPage < minimumPage && [panGes velocityInView:self.view].x < 0) || (currentPage > maximumPage && [panGes velocityInView:self.view].x > 0))
            return NO;
    }
    return YES;
}

5) Анимация закончена

- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
{
    pageAnimationFinished = YES;
}

Я слишком много играл с ней и, похоже, это хорошее решение, которое хорошо работает.

6
ответ дан Community 25 August 2018 в 12:46
поделиться

Как насчет этого:

- (void)pageViewController:(UIPageViewController*)pgVC willTransitionToViewControllers:(NSArray*)pendingVCs
{
    pgVC.dataSource = nil; // ... to disallow user to change pages until animation completes
}

- (void)pageViewController:(UIPageViewController*)pgVC
        didFinishAnimating:(BOOL)finished
   previousViewControllers:(NSArray*)prevVCs
       transitionCompleted:(BOOL)completed
{
    if(completed || finished) {
        pgVC.dataSource = _pgViewDataSource; // ... to allow user to change pages again
    }
}
1
ответ дан Leo Thiessen 25 August 2018 в 12:46
поделиться

Вот версия Swift версии Билла Чесвика (в настоящее время главный ответ):

Добавьте переменную, чтобы удерживать текущее состояние:

var pageIsAnimating = false

Установите анимационное состояние:

func pageViewController(pageViewController: UIPageViewController, willTransitionToViewControllers pendingViewControllers: [UIViewController]) {
    self.pageIsAnimating = true
}

func pageViewController(pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
    if finished || completed {
        self.pageIsAnimating = false
    }
}

Заблокировать переходы, если он в настоящее время оживляет:

func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
    if self.pageIsAnimating {
        return nil
    }

    // Your code here
}

func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
    if self.pageIsAnimating {
        return nil
    }

    // Your code here
}

Спасибо, Билл Чесвик!

3
ответ дан Mr Stanev 25 August 2018 в 12:46
поделиться

Вот версия QUICK с использованием делегата:

добавьте этот код (убедитесь, что вы включили UIPageViewControllerDelegate в свой заголовок или расширение класса и назначили self.pageViewController.delegate = self;):

- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers {
   self.pageAnimationFinished = NO;
}

- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed {
    self.pageAnimationFinished = YES;
}

, затем проверьте self.pageAnimationFinished и верните нуль, если это == NO.

Дольше Объяснение:

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

Мы можем использовать этот метод делегата из UIPageViewControllerDelegate знать, когда анимация перелистывает или проскакивает через страницы. Используя это, мы можем реализовать это следующим образом:

- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed {
    pageAnimationFinished = YES;
}

, тогда просто верните nil в свои

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(PageViewController *)viewController

и

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(PageViewController *)viewController

когда

pageAnimationFinished == NO. Обязательно установите pageAnimationFinished на NO, когда вы живете. Лучший способ узнать, когда вы живете, - это использовать противоположность

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

, а именно:

- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers

С тех пор я не видел этого предупреждения, и это можно сделать в 1/3 линии, как и другие решения. И намного проще следовать.

5
ответ дан smileBot 25 August 2018 в 12:46
поделиться

Используйте методы UIPageViewControllerDelegate и настройте защиту, чтобы предотвратить создание новых просмотров страниц при обнаружении чрезмерных поворотов страниц.

  1. Вы можете отключить распознаватели жестов
  2. Установить " userInteraction ", который отключен на UIView
  3. , поддерживает флаг в UIPageViewController, чтобы игнорировать дальнейший ввод, когда происходит анимация. (предупреждение об этой опции .. ios5 и ios6 имеют разные способы определения начала анимации ..)
0
ответ дан timzilla 25 August 2018 в 12:46
поделиться

Мне пришлось добавить его в viewDidAppear: чтобы он работал

    - (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    self.pageAnimationFinished = YES;
}
0
ответ дан ميكايل باينوف 25 August 2018 в 12:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: