UIPageViewController в iOS6

В iOS6 в методите viewControllerAfterViewController и viewControllerBeforeViewController, ако върна нула (за блокиране на навигацията в страницата, когато съм в първата или последната страница), приложението се срива със следното изключение:

„Броят предоставени контролери за преглед (0) не съвпада с необходимия брой (1) за искания преход“

В iOS5 всичко работи добре.


person Mattia Lancieri    schedule 24.09.2012    source източник
comment
Интересно е, че нито едно от решенията на тази страница не включва свойството doubleSided на UIPageViewController. Това беше проблемът за мен... или поне за един от тях.   -  person livingtech    schedule 16.07.2013


Отговори (5)


Имах същия проблем. Открих, че причината е замяната на делегата на UIPanGestureRecognizer на UIPageViewController, наистина не-не. Панелът за разпознаване на жестове извикваше недокументиран метод _gestureRecognizerShouldBegin: (обърнете внимание на водещата долна черта), който UIPageViewController внедрява и очевидно разчита, за да работи правилно (да се чете: без срив). В крайна сметка внедрих respondsToSelector: и forwardingTargetForSelector: в моя клас, който използва UIPageViewController, за да прехвърли недокументирания метод на делегиране към UIPageViewController, без да го наименува конкретно (и почти сигурно ми спечели отказ от преглед на магазина за приложения).

-(BOOL)respondsToSelector:(SEL)aSelector {
    if ([super respondsToSelector:aSelector])
        return YES;
    else if ([self.pageViewController respondsToSelector:aSelector])
        return YES;
    else
        return NO;
}

- (id)forwardingTargetForSelector:(SEL)aSelector {
    if ([super respondsToSelector:aSelector]) {
        return nil;
    } else if ([self.pageViewController respondsToSelector:aSelector]) {
        return self.pageViewController;
    }
    return nil;
}

Моето по-дългосрочно решение ще бъде да преработя използването на UIPageViewController, така че да не е необходимо да измествам делегатите за разпознаване на жестове.

person rrrus    schedule 24.09.2012
comment
+1. В крайна сметка НЕ ​​ЗАМЕНЯ panGestureRecognizer.delegate като мой viewController. - person inamiy; 25.09.2012
comment
така че... не разбирам. това решение води ли до отхвърляне на приложението ви? така че може би е по-добре да приемем предложението на @puneeth? - person n.evermind; 03.11.2012
comment
Това ще бъде ли отхвърлено от Apple? - person Bagusflyer; 17.11.2012
comment
itux.idev.pro/2012/12 / ... използвайте два uiviewcontroller и динамично зареждайте страници и вашата корекция спестява и моето време.. Страхотно благодаря, и вярвам, че Apple не отхвърли нашето приложение :) - person iTux; 03.12.2012

Ах, чудех се защо никой не е посочил този бъг, което ми отне почти 2 нощи, за да намеря решението.

СТАР КОД (iOS 5.1): когато върнете нула на първата и последната страница, ще изпитате срив на приложението. Работи добре в iOS 5.1, но в iOS 6 няма.

- (UIViewController *)pageViewController:
(UIPageViewController *)pageViewController viewControllerBeforeViewController:
(UIViewController *)viewController
{
    for (UIGestureRecognizer *recognizer in pageController.gestureRecognizers) {
        if ([recognizer isKindOfClass:[UITapGestureRecognizer class]]) {
            recognizer.enabled = NO;
        }
    }
    NSUInteger index = [self indexOfViewController:
                        (MainViewController *)viewController];
    if ((index == 0) || (index == NSNotFound)) {
        return nil;
    }

    index--;
    return [self viewControllerAtIndex:index];
}
- (UIViewController *)pageViewController:
(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
    for (UIGestureRecognizer *recognizer in pageController.gestureRecognizers) {
        if ([recognizer isKindOfClass:[UITapGestureRecognizer class]]) {
            recognizer.enabled = NO;
        }
    }
    NSUInteger index = [self indexOfViewController:
                        (MainViewController *)viewController];
    if (index == NSNotFound) {
        return nil;
    }
}

РЕШЕНИЕ(iOS 6): След като добавите ефекта на жеста към суперизгледа, просто извикайте делегата, наречен -(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer. Това, което направих, е съвсем просто, изчислявайки скоростта на потребителя, който обръща първата и последната страница (имам предвид използването на разпознавателя на жестове), отказах плъзгането. Всичко, което трябва да направите, е просто да поставите следния код и сте ГОТОВИ !.

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
    if (pageNum==0) {

        if ([(UIPanGestureRecognizer*)gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] &&
            [(UIPanGestureRecognizer*)gestureRecognizer velocityInView:gestureRecognizer.view].x > 0.0f) {
            //NSLog(@"Swiping to left on 1st page is denied");
            return NO;
        }
        if ([(UITapGestureRecognizer*)gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]] &&
            [(UITapGestureRecognizer*)gestureRecognizer locationInView:gestureRecognizer.view].x < self.view.frame.size.width/2) {
         //NSLog(@"tapping to left on 1st page is denied");
            return NO;
        }
    }

    else if(pageNum ==totalNoOfFiles-1)
    {

        if ([(UIPanGestureRecognizer*)gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] &&
            [(UIPanGestureRecognizer*)gestureRecognizer velocityInView:gestureRecognizer.view].x < 0.0f) {
            //NSLog(@"Swiping to right on 1st page is denied");
            return NO;
        }
        if ([(UITapGestureRecognizer*)gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]] &&
            [(UITapGestureRecognizer*)gestureRecognizer locationInView:gestureRecognizer.view].x > self.view.frame.size.width/2) {
          //NSLog(@"Tapping to right on 1st page is denied");
            return NO;
        }
    }

    return YES;
}


- (UIViewController *)pageViewController:(UIPageViewController*) pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
 {
  int index = [self indexOfViewController:(ChildViewController *)viewController];
                index--;

    return [self viewControllerAtIndex:index];
}


- (UIViewController *)pageViewController:
(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
    int index = [self indexOfViewController:(ChildViewController *)viewController];

            index++;
     return [self viewControllerAtIndex:index];
}
person Master Stroke    schedule 08.10.2012
comment
Това изглежда е работило най-добре за мен, с изключение на това, че използвах по-голям праг на скоростта от 0,0, защото грешката изглежда е по отношение на много бързите движения на панорамата. - person jsbox; 26.02.2019

Това беше добре обсъдено, но имам нещо да добавя. Помислете защо задавахте делегата на разпознавателите на жестове на себе си. В моя случай това беше, защото в някои случаи исках да попреча на разпознаващите жестове да разпознават с gestureRecognizerShouldBegin: на делегата.

Но в iOS 6, където възниква този проблем, има изцяло нов начин да се направи точно това, чрез внедряване на gestureRecognizerShouldBegin: в UIView. (Това е нов метод на екземпляр на UIView в iOS 6.)

Така успях да постигна точно това, което постигах преди, без да променям делегата на разпознавателите на жестове.

person matt    schedule 17.10.2012
comment
Това е най-добрият отговор. Въпреки това, самата документация пропуска детайл, който е споменат в заглавката на UIView.h: извиква се, когато разпознавателят се опита да премине от UIGestureRecognizerStatePossible, ако докосване, тествано за този изглед, ще бъде отменено в резултат на разпознаване на жестове< /i>. Това означава, че трябва да подкласифицирате изгледа, че докосването е било тествано при удар, към което иначе не бихте могли; в моя случай трябваше да направя подклас UISlider само за да внедря този метод. - person Charles A.; 12.05.2015

Имах проблем с UIPageViewController, който се срива с iOS6 със същата грешка („Броят на предоставените контролери за изглед (0) не съвпада с необходимия брой (1) за искания преход“).

Нито едно от горните решения не работи за мен, но в крайна сметка открих, че преместването на следния ред от viewDidLoad на viewDidAppear го коригира.

self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;
person Liam    schedule 19.11.2012
comment
Това не елиминира срива за мен. - person Dan Reese; 04.06.2014

Напълно същия проблем тук.

Това, което направих, беше актуална корекция, която само за да върне клонинг на before/afterViewController вместо нула, т.е.

// viewController = before/afterViewController
NSUInteger index = [self indexOfViewController:viewController];

// NOTE: return nil crashes in iOS6
return [self viewControllerAtIndex:index storyboard:viewController.storyboard];

Това означава, че можете да извивате страницата завинаги, но нямах друг избор... По-доброто решение винаги е добре дошло.

person inamiy    schedule 24.09.2012