2

これに関して多くの質問があることは承知していますが、私が知る限り、これはユニークな状況なので、投稿することにしました. うまくいけば、これがなぜこれが私たちに起こっているのかについての答えを最終的に与えるかもしれないいくつかの情報を追加する. デバイスが回転すると、エラー: wait_fences: failed to receive reply: 10004003 が表示されます。ビューのアニメーションは次から開始されます。

- (void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration

新しい iPad 3 でのみエラーが発生します。元の iPad と 3GS までの iPhone でまったく同じプログラムを使用しました。それらはすべて wait_fences エラーを取得せず、iPad 3 よりも高速に回転します。

ビューを描画するために、ほぼ独占的に Core Graphics を使用しています。また、サイズ変更時に再描画されるようにして、頭がおかしくなったビューが表示されないようにします。サイズ変更時に再描画を無効にすると、このエラーは発生しません (ただし、ビューが引き伸ばされます)。コア グラフィック描画を完全に無効にすると、エラーは発生しません (ただし、もちろん、黒いビューが表示されます)。

Time Profiler を使用したところ、ハングアップは主にグラデーションの描画にあることがわかりました。 ここに画像の説明を入力

グラデーションを描画するのではなく、塗りつぶすようにコードを変更しました。これにより、問題が軽減されます。これらのアニメーションを他の状況 (回転に反応する場合以外) で行うことを除いて、グラデーションが問題であると言えますが、それは問題なく機能します。

また、実際に画面に表示されているビューのみをアニメーション化するように特に注意を払っていることにも注意してください。画面外のビューをアニメーション化すると、このエラーが発生することがあります。

アニメーションコードを含めていません

なぜこれが起こっているのかについてのアイデアはありますか? 特にiPad 3でしか起きていないので?

質問する人のために、これはアニメーションを実行するコードです。通常、UIView アニメーション ブロックにラップされます。

- (void) setFramesForFocusView:(CustomControl *)focusView atX:(CGFloat)x showInput:(BOOL)showInput{
    CGSize bSize = self.bounds.size;
    CGRect fRect = focusView.frame;
    fRect.size.width = bSize.width;

    CGRect iRect;
    if (focusView.inputViewIsSystemKeyboard){
        if (_keyboardRect.origin.y < 0 || _keyboardRect.origin.y >= CGRectGetMaxY(self.bounds) || CGRectIsEmpty(_keyboardRect) || CGRectGetMaxY(_keyboardRect) > CGRectGetMaxY(self.bounds)) return;
        iRect = _keyboardRect;
    } else {
        iRect = (focusView.inputUIView && showInput) ? CGRectMake(0, bSize.height / 2, bSize.width, bSize.height / 2) : CGRectZero;
    }

    CGRect iaRect = focusView.inputAccessoryUIView.frame;
    CGFloat availableFieldHeight = iRect.origin.y - iaRect.size.height;

    iRect.size.width = bSize.width;
    iaRect.size.width = bSize.width;

    if (!showInput){
        iRect.origin.y = bSize.height;
    }
    iaRect.origin.y = iRect.origin.y - iaRect.size.height;

    iRect.origin.x = x;
    iaRect.origin.x = x;
    focusView.inputUIView.frame = iRect;
    focusView.inputAccessoryUIView.frame = iaRect;

    if (focusView.expandInput){
        fRect.origin.y = 0;
        fRect.size.height = availableFieldHeight;
    } else {
        if (focusView.labelPlacement != LabelPlacementTop && focusView.labelPlacement != LabelPlacementBottom){
            fRect.size.height = _currentView.storedFrame.size.height + [focusView.label.text sizeWithFont:focusView.label.font].height; 
        }
        fRect.origin.y = availableFieldHeight - fRect.size.height;
    }
    if (fRect.size.height > availableFieldHeight){
        fRect.origin.y = 0;
        fRect.size.height = availableFieldHeight;
    }
    fRect.origin.x = x;
    [focusView setLabelPlacement:LabelPlacementTop toFrame:fRect];
}
4

1 に答える 1

1

まあ速かったです。@RobNapier は、タイミングの問題であるという点で正しかったです。私は自分のアニメーションをコメント アウトしましたが、その背後には他の多くのビューがアニメーション化されていました! 画面上のビューのみを明示的にアニメーション化していたにもかかわらず、別の ViewController が私のビューの背後で回転イベントを受け取っていましたが、私の... ええと... 知らないでしょうか? つまり、私は知っているべきですよね?コードを書きました。ビューのセットが画面全体をカバーしていたので、最初は気づきませんでした。残念ながら、これには多くの書き直しが必要になります。カスタム コンテナ コントローラを使用していますが、実装を再検討する必要があることがわかりました。多くのものが不必要に回転/アニメーション化されています。しかし、うわー...それは多くのパフォーマンスの質問に答えました....

アップデート

そのため、私が直面している問題は、他のビュー コントローラーによってアニメーション化されている余分なビューに関係していると考えていました。ただし、これは技術的には真実ですが、私が思ったほど、または私が思ったようには真実ではありません. ウィンドウからルートビュー階層全体を削除し、回転させたいビューコントローラーのみに置き換えることで、他のビューがアニメーション化されていないことを完全に確認しました。これは間違いなく役に立ちましたが、完全ではありませんでした。本当に、「バーを下げた」だけなので、「wait_fences」エラーが発生する可能性が低くなりました。特定の状況では、エラーが発生していることをまだ発見しました。

私が抱えている問題は、UIScrollView の使用にあると思います。私の実装には、管理する可変数のサブビューがあります。特定のビューは、UIPickerView の私自身のカスタム実装であるため、ご想像のとおり、管理するビューの数は非常に多くなる可能性があります。これらのサブビューが多すぎると、「wait_fences」エラーが発生し始めることがわかりました。

UIScollViewがアニメーション化されている場合、サブビューが画面上になくても、すべてのサブビューがアニメーション化されます。 これは重要。むしろ、このエラーに苦しんでいる多くの人がこれに気付いていないのではないかと思います. これらの画面外のサブビューのそれぞれが、「wait_fences」エラーに近づきます。私の場合の解決策は「簡単」です。UIScrollView を UITableView に変換します。これは多くのコードを書き直すことを意味しますが、少なくとも、画面外のサブビューが画面から削除されるため、アニメーション化されないことはわかっています。

他にも気になったことがあります。Core-Graphic Gradients はあなたに大きな打撃を与えます。グラデーションを使用しない場合は、より多くのオフスクリーン ビューをアニメーション化できます。もちろん、私はグラデーションが大好きで、それを放棄するつもりはありません (これが、私が PickerView を書き直した理由です) が、興味深い点であり、注意することが重要です。

更新 2

私の UIScrollView を tableView として書き直して、それでうまくいったようです。画面を回転させても、ラグやwait_fencesエラーは発生しません。

更新 2

そうですね、wait_fences他の iPad/iPhone よりも iPad 3 でエラーが発生しやすいのです。画面に表示されていないものをアニメーション化しないようにすべてのコードを調べたので、その問題は解決しました。wait_fences「重い」描画ルーチンを使用すると、iPad 3でもエラーが発生します。私が見つけたものは私をヒットさせます:

  1. グラデーション: グラデーションは、Retina スクリーン上で CPU を実際に動作させます。
  2. 透明度: ビューが不透明でない場合、CPU はビューの透明な領域を見つけようと懸命に働きます。
  3. 透明色: ビューの透明度とは異なります。これは、光沢やハイライトなどの「効果」を得るために、透明な色/グラデーションを重ね合わせています。
  4. テクスチャ: テクスチャを使用すると、wait_fencesエラーが発生する可能性が少し高くなりますが、グラデーション/透明度のようにはなりません。
于 2012-06-07T19:52:44.793 に答える