8

これは ios6 で発生し始めたばかりですが、ページ ビュー コントローラー テンプレートを使用して新しいプロジェクトを開始した場合に発生します。次に

PCRootViewControlle::viewDidLoad()

メソッドの一番下に行を追加します。

for (UIGestureRecognizer *gR in self.pageViewController.gestureRecognizers)
{
    gR.delegate = self;
}

UIGestureRecognizerDelegate に準拠し、メソッドを実装するように、viewController を割り当てる必要があります。

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch (UITouch *)touch
{
    return YES;
}

ここで、アプリを実行して境界を越えてページをめくろうとすると、つまり 1 月に移動して元に戻そうとすると、

  • (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController

nil を返します。

その後、アプリがクラッシュします。

これは、ios5 では発生しませんでした。pageViewController で常にタッチ イベントを処理する必要があるとは限らないため、gestureRecognizer デリゲートを viewController に割り当てる必要があります。

他の誰かがこれを経験したり、私が何か間違ったことをしていると指摘したりしましたか?

どうもありがとうスチュワート。

4

4 に答える 4

8

ついに私の問題の解決策を見つけ、それが私を悲しませたので、うまくいけば、これが他の誰かを助けることができます。

問題は、pageViewControllersデリゲートをviewControllerに設定した場合です

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

その後、からnilを返します

pageViewController:viewControllerAfterViewController:

クラッシュします!! iOS6のみ!!

私の問題は、いくつかの状況でpanGestureをインターセプトする必要があるため、つまり、ボタンがいくつかあるためにユーザーがページの特定の部分に触れているときにページをめくることができないため、gestureRecognisersのデリゲートを設定する必要があることでした。

解決策は、

pageViewController:viewControllerAfterViewController: 

の中へ

gestureRecognizer:shouldReceiveTouch:

それからNOを返す限り、それは電話をかけ続けないからです

pageViewController:viewControllerAfterViewController:

したがって、nilを返してクラッシュする必要はありません。

ただし、これはシーケンスの最初と最後のページでは機能しませんでした。たとえば、最初のページで、ページを前に戻すことを許可しますが、後ろに戻すことはできません。そこで、渡されたGestureRecogniserを確認し、PanGestureにキャストして、速度を確認します。速度が戻ることを意味する場合(> 0.0f)、NOを返します。これは良さそうに聞こえましたが、ベロシティは常にゼロでした。

次に、GestureRecognizerデリゲートで次のような非常に役立つ小さな関数を見つけました。

gestureRecognizerShouldBegin:gestureRecognizer

この関数は後に呼び出されます

gestureRecognizer:shouldReceiveTouch:

ただし、今回はジェスチャからの速度が予想どおりであるため、速度を確認して、最初のページが0.0fを超える場合にのみYESを返すことができます。

于 2012-09-27T16:27:16.523 に答える
7

noRema が言及したように既存の pageViewController コードをリファクタリングしたり、ここで述べたようにセレクタ転送をいじったりするよりもはるかに複雑でない解決策を見つけたと思いますが、参照としてこれらの両方の解決策がなければ決して見つけられなかったでしょう。

これは、わずかな調整だけで、任意の UIPageViewController プロジェクトに簡単に組み込むことができます。

実装するには、コードをそのまま残します。これは UIGestureRecognizer Delegate の動作にのみ影響するため、既存のロジックはすべて同じままにする必要があります。ジェスチャ デリゲート メソッド - (BOOL)gestureRecognizerShouldBegin: を次のようにオーバーライドします。

注: 私は Apple の Page-Based Application コードを出発点として使用しているので、用語が混乱する場合はそれを参照して_modelControllerください_pageViewController

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{

    //Make sure we're not trying to turn backward past the first page:
    if ([_modelController indexOfViewController:[_pageViewController.viewControllers objectAtIndex:0]] == 0) {
        if ([(UIPanGestureRecognizer*)gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] &&
            [(UIPanGestureRecognizer*)gestureRecognizer velocityInView:gestureRecognizer.view].x > 0.0f) {
            NSLog(@"DENIED SWIPE PREVIOUS ON FIRST PAGE");
            return NO;
        }
        if ([(UITapGestureRecognizer*)gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]] &&
            [(UITapGestureRecognizer*)gestureRecognizer locationInView:gestureRecognizer.view].x < self.view.frame.size.width/2) {
            NSLog(@"DENIED TAP PREVIOUS ON FIRST PAGE");
            return NO;
        }
    }

    //Make sure we're not trying to turn forward past the last page:
    int finalVCindexSubtractor;
    if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation)) {
        // the vc we compare is a different distance from the end based on our orientation:
        finalVCindexSubtractor = 2;
    } else {
        finalVCindexSubtractor = 1;
    }
    if ([_modelController indexOfViewController:[_pageViewController.viewControllers objectAtIndex:0]] == _modelController.pageData.count-finalVCindexSubtractor) {
        if ([(UIPanGestureRecognizer*)gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] &&
            [(UIPanGestureRecognizer*)gestureRecognizer velocityInView:gestureRecognizer.view].x < 0.0f) {
            NSLog(@"DENIED SWIPE NEXT ON LAST PAGE");
            return NO;
        }
        if ([(UITapGestureRecognizer*)gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]] &&
            [(UITapGestureRecognizer*)gestureRecognizer locationInView:gestureRecognizer.view].x > self.view.frame.size.width/2) {
            NSLog(@"DENIED TAP NEXT ON LAST PAGE");
            return NO;
        }
    }
    return YES;
}
于 2012-10-04T18:41:12.693 に答える
4

iOS 6のUIPageViewControllerでパンジェスチャの問題を調査しているときに、1つのジェスチャ内でビューコントローラメソッドの前後を数回呼び出す可能性があることに気付きました。次/前のページに移動できるようにするには、ページめくりごとにアニメーションが終了するまで待つ必要があるため、これは私の特定のケースでは悪いことです。したがって、私たちのメソッドはそのような構造を持っています:

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
    if (animationInProgress)
        return nil;
    UIViewController *result = nil;
    //do stuff to init result controller for next/prev page
    if (result)
        animationInProgress = YES;
    return result;
}

メソッドについても同じですviewControllerAfterViewController

そして、アニメーションが終了した後、UIPageViewControllerDelegateのこのメソッドが呼び出されます。

- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed {
        animationInProgress = NO;
        //do other stuff to handle finishing animation.
}

PanGestureが数回呼び出され、viewControllerAfterViewControllerそのために別のメソッドが数回呼び出されたため、残念ながらdidFinishAnimatingこの場合はメソッドが呼び出されなかったため、animationInProgressフラグがYES常に設定され、ユーザーはページをまったくナビゲートできませんでした。注:iOS6でのみ発生します。

その問題を修正するには、なんとかしてPanGestureを処理する必要がありました。UIView gestureRecognizerShouldBegin:gestureRecognizer(iOS 6で追加された)を使用しても問題はまったく解決されませんでした。ジェスチャのデリゲートとしてコントローラーを設定すると、before/afterメソッドからnilが返されるときにクラッシュが発生します。したがって、PanGestureが状態にある場合に、コントローラーメソッドの前後を呼び出さないロジックを追加しようとしましたUIGestureRecognizerStateChanged(ループ内のメソッドを呼び出すときのジェスチャー状態を判別するためのテストに基づいて調査されました)。

次のようなメソッドを追加することにより:

- (BOOL)skipIfPanGestureInProgress {
    BOOL shouldSkip = NO;
    if(pvcPanGestureRecognizer && [pvcPanGestureRecognizer state] == UIGestureRecognizerStateChanged){
        animationInProgress = NO;
        shouldSkip = YES;
    }
    return shouldSkip;
}

その後、メソッドは次のようになります。

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
    if([self skipIfPanGestureInProgress]){
        return nil;
    }
    if (animationInProgress)
        return nil;
    UIViewController *result = nil;
    //do stuff to init result controller for next/prev page
    if (result)
        animationInProgress = YES;
    return result;
}

これは、animationInProgressフラグのループの問題を解決するのに役立ちました。

これが誰かに役立つことを願っています。

于 2012-11-26T09:35:12.370 に答える
2

境界を越えて移動するときに同じエラーで iOS6 で UIPageViewController がクラッシュするという同じ問題がありました。

上記の解決策はどれもうまくいきませんでしたが、最終的に次の行を移動して完全viewDidLoadviewDidAppear修正したことがわかりました。

self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;
于 2012-11-19T17:21:55.640 に答える