web-dev-qa-db-ja.com

UIPageViewControllerのアサーションエラー

UIPageViewControllerでタブの切り替えが速すぎると、アプリがクラッシュします

[UIPageViewController queuingScrollView:didEndManualScroll:toRevealView:direction:animated:didFinish:didComplete:]

不明な例外「NSInternalInconsistencyException」によるエラーアサーションエラーとアプリの終了、理由:「表示ビューを管理するビューコントローラーがありません。

以下のエラーログ

*** Assertion failure in -[UIPageViewController queuingScrollView:didEndManualScroll:toRevealView:direction:animated:didFinish:didComplete:], /SourceCache/UIKit/UIKit-3318.0.1/UIPageViewController.m:1875
2014-09-29 11:34:00.770 Wowcher[193:9460] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'No view controller managing visible view <UIView: 0x1783fa80; frame = (0 0; 320 416); autoresize = W+RM+H+BM; layer = <CALayer: 0x17898540>>'
*** First throw call stack:
(0x219fbf87 0x2f15ac77 0x219fbe5d 0x226cb2c9 0x253f9fff 0x2546f8d3 0x2546f6b7 0x2546c2b9 0x254700db 0x25470f97 0x2546d037 0x24ea925f 0x2500a589 0x24ff7eef 0x24ea677d 0x252b8c81 0x24e70105 0x24e6e07f 0x24ea4b6d 0x24ea443d 0x24e7acc5 0x250ee513 0x24e79707 0x219c2807 0x219c1c1b 0x219c0299 0x2190ddb1 0x2190dbc3 0x28c99051 0x24ed9a31 0xd950b 0xca6e0)
libc++abi.dylib: terminating with uncaught exception of type NSException

前もって感謝します

39
Brjv

したがって、これに対する私の解決策は、アニメーションの状態を追跡するBOOLを追加することでした。新しいViewControllerを設定する前に、これも変更します。

if (!_transitionInProgress) {
    _transitionInProgress = YES;
    [self.pageController setViewControllers:@[viewController] direction:UIPageViewControllerNavigationDirectionReverse animated:YES completion:^(BOOL finished) {
        _transitionInProgress = !finished;
    }];
}

そこで、アニメーションが完了するのを待ってから、新しいView Controllerを設定します。私の場合、ユーザーがページを切り替えるために押すことができるボタンがいくつかあります。これにより、アニメーションが高速になりすぎないようになり、アニメーションは常にスムーズで素敵です

24
Andrei Filip

これは、スクロールモードでのUIPageViewControllerの内部実装のバグです。これは、Page View Controllerが既にトランジションをアニメーション化している間にトランジションアニメーションが発生したときに発生します。私がやったことは、UIが複数のクイックスクロールを許可しないようにすることでした。左と右の2つのボタンがあり、Page View Controllerを前または次のPage Controllerにスクロールします。アニメーションが進行している間、ボタンの操作を無効にします。 Page View Controllerのデリゲートは、すべてのアニメーションが停止したら、UIの機能をいつ無効にし、再び有効にするかを知る必要があることをすべて伝えます。

10
Leo Natan

私もこの問題に直面していますが、問題は一貫して問題を再現できないことですが、クラッシュログから問題が存在することがわかります。

ユーザーがスワイプできるようにするpageviewcontrollerがあり、プログラムでビューをスクロールできます。画面に入るだけでアプリがクラッシュすることがありますが、次の試行では正常に動作するため、一種の狂気です。修正を加えたとしても、それを再現することができないため、それが機能することを確信できません。以下のコードで修正する必要があります( IPageViewControllerからView Controllerを削除する から取得)このコードでは、画面の動作が改善されます。このクラッシュを自分で挿入する方法を入手できれば、修正を確認できます。

- (void) setViewControllers:(NSArray*)viewControllers direction:(UIPageViewControllerNavigationDirection)direction animated:(BOOL)animated completion:(void (^)(BOOL))completion {

    if (!animated) {
        [super setViewControllers:viewControllers direction:direction animated:NO completion:completion];
        return;
    }

    [super setViewControllers:viewControllers direction:direction animated:YES completion:^(BOOL finished){

        if (finished) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [super setViewControllers:viewControllers direction:direction animated:NO completion:completion];
            });
        } else {
            if (completion != NULL) {
                completion(finished);
            }
        }
    }];
}
3
anoop4real

ここには本当に良い議論があります:

IPageViewControllerからView Controllerを削除する

受け入れられた答えはこれを論議します:

「これがなぜ起こったのか正確にはわからず、私はバックトラックし、最終的にJaiの答えを解決策として使い始め、まったく新しいUIPageViewControllerを作成し、UINavigationControllerにプッシュし、古いものをポップしました。しかし、それは動作します。ほとんどの場合、次のようにUIPageViewControllerからアサーションエラーが時々発生することがわかりました。

  • -[UIPageViewController queuingScrollView:didEndManualScroll:toRevealView:direction:animated:didFinish:didComplete:]、/ SourceCache/UIKit_Sim/UIKit-2380.17/UIPageViewController.m:1820 $ 1 = 154507824表示ビューを管理するビューコントローラーでのアサーションエラー>

そして、アプリがクラッシュします。どうして?さて、検索して、私は上で言及したこの他の質問、特にsetViewControllers: animated:YESを呼び出してからsetViewControllers: animated:NOの呼び出しが完了するとすぐに、元のアイデアを支持する受け入れられた答えを見つけましたコントローラーを表示してUIPageViewControllerをリセットしますが、要素がありません。そのコードをメインキューで呼び出します!コードは次のとおりです。」

1
Steve Rosenberg

私も同じ状況に直面し、私のアプリは前後に移動するためのスワイプと次と前の両方のボタンを持っています。この問題を解決するには、初期化中にローカルBool変数をtrueに設定します(private varcanScroll:Bool =true)その後、ガードを使用してナビゲーションメソッドの最初の行の条件を確認し、Bool値をfalseに設定しますbefore setViewcontrollerメソッド。アニメーションの完了時に同じブール値をtrueに設定し、View Controllerの移行中にスワイプアクションを実行すると、ガードステートメントがcanScroll返されない場合はtrueになります。それが、次のページングのクラッシュの問題を回避する方法です。次のアクションのコードです。

 @IBAction func nextAction(_ sender: Any) {
            guard canScroll == true else { return } //check condition
            guard featureCount > 0 else { return }
    guard let index = self.viewControllerAtIndex(indexRow) else { return }
            let startingViewController: OnBoardModelViewController = index
            canScroll = false 
            pageViewController?.setViewControllers([startingViewController],
                                                   direction: UIPageViewControllerNavigationDirection.forward,
                                                   animated: true,
                                                   completion: {_ in
                                                    self.canScroll = true
            })
}
0
iVignesh

UIPageViewControllerサブクラスにedgesForExtendedLayout = UIRectEdgeNoneを設定することで問題を修正しました。

- (instancetype)initWithTransitionStyle:(UIPageViewControllerTransitionStyle)style navigationOrientation:(UIPageViewControllerNavigationOrientation)navigationOrientation options:(NSDictionary<NSString *,id> *)options
{
    self = [super initWithTransitionStyle:style navigationOrientation:navigationOrientation options:options];

    self.edgesForExtendedLayout = UIRectEdgeNone;

    return self;
}
0
Aron Balog