5

親UIScrollViewをズームインすると、CATiledLayerで再描画の問題が発生します。

CATiledLayerでバックアップされたUIViewでPDFページをレンダリングしています。その背後には別のUIImageViewがあり、CATiledLayerが描画するページの低解像度の画像が含まれています。ズームインすると、期待どおりに機能します。CATiledLayerは、ズームレベルに応じてより高解像度の画像をレンダリングします。

ズーム後に問題が発生します。ズームインしてiPadをそのままにしておくと、表示された画像がぼやけてから鮮明になります。バッキングビューにぼやけた低解像度の画像が表示されるため、CATiledLayerが削除されているように見えます。その後、CATiledLayerが再描画されます。つまり、タイリング効果と画像の再シャープネスが表示されます。これは、アプリをそのままにして30〜40秒待つと発生します。私はそれをiPadの第3世代(新しいiPad、iPad3など)でしか観察していません。iPad2でもテストしていますが、まだ問題は発生していません。

他の誰かがこの問題に遭遇しましたか?既知の原因と、場合によっては解決策はありますか?

編集:

私のUIScrollViewDelegateメソッドは次のとおりです。

// currentPage, previousPage, and nextPage are the pdf page views
// that are having the refresh problem 

- (void)positionBufferedPages { 
  // performs math {code omitted}

  // then sets the center of the views
  [previousPage.view setCenter:...];        
  [nextPage.view setCenter:...];
}

- (void)hideBufferedPages {
  if ([previousPage.view isDescendantOfView:scrollView]) {
    [previousPage.view removeFromSuperview];
  }

  if ([nextPage.view isDescendantOfView:scrollView]) {
    [nextPage.view removeFromSuperview];
  }          
}

- (void)showBufferedPages {
  if (![previousPage.view isDescendantOfView:scrollView]) {
    [scrollView addSubview:previousPage.view];
  }

  if (![nextPage.view isDescendantOfView:scrollView]) {
    [scrollView addSubview:nextPage.view];
  }

  if (![currentPage.view isDescendantOfView:scrollView]) {
    [scrollView addSubview:currentPage.view];
  }
} 

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
  return currentPage.view;
}

- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view {
  [self hideBufferedPages];
}

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollViewParam withView:(UIView *)view atScale:(float)scale {
  [self positionBufferedPages];
  [self showBufferedPages];    
}

- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
  // nothing relating to the pdf page view
  // but does set the center of some other subviews on top of the pdf page views
}

問題が発生している間、scrollviewは入力を受け取らないため、これがどれほど役立つかはわかりません。上記のように、PDFページがCATiledLayerにロードされ、iPadをそのままにして(デバイスが入力を受信しない)、CATiledLayerが自動的に再描画します。

setNeedsDisplayまた、ビューとタイルレイヤーの両方でsetNeedsDisplayInRect:、、、の呼び出しをキャッチしようとsetNeedsLayoutしましsetNeedsDisplayOnBoundsChange:たが、これらの関数が呼び出されることなく再描画が行われます。drawLayer:inContext:もちろん、が呼び出されますが、トレースには、バックグラウンドスレッドで開始された一部のQuartz呼び出しのみが示されているため(タイルレイヤーがバックグラウンドでコンテンツを準備するため、予想どおり)、それも役に立ちません。

前もって感謝します!

4

4 に答える 4

2

アプリのメモリ使用量はどのようになっていますか?CATiledLayerは、メモリ警告が発生した場合、キャッシュを破棄して再描画します。アプリにメモリ警告が送信されなくても(通常のメモリ負荷よりも高い)、これを実行することを確認しました。Instrumentsを使用してメモリ使用量を確認します。グラフィックメモリで何が起こっているかを確認するには、OpenGLESドライバインスツルメントを使用する必要がある場合があります。

于 2012-05-11T11:35:31.963 に答える
2

私はこれについてAppleのエンジニアと話をしましたが、簡単に言うと、iOSにはCATiledLayerのキャッシュに使用できるメモリがX個しかなく、iPadのRetinaディスプレイでは、ピクセルが多すぎて複数のレイヤーを使用できません。

私は2つのCATileLayersを使用して、マップビューと描画ビューを上に表示していました。2番目のCATiledLayerを削除すると、問題は解決しました。

于 2012-06-01T01:24:42.350 に答える
1

私はまったく同じ問題を抱えていました。私の場合、UIGraphicsBeginImageContext()関数を使用したことが原因でした。この関数はスケールを考慮していないため、Retinaディスプレイで問題が発生します。解決策は、呼び出しをUIGraphicsBeginImageContextWithOptions()に置き換え、scale(= third)パラメーターを0.0に設定することでした。

私のように、AppleのZooming PDF Viewerサンプルコードに基づいてコードを作成した場合、これで問題も解決する可能性があります。

于 2012-05-03T14:00:55.783 に答える
1

ロングショット、非メインスレッドからのビューでメソッドを呼び出す可能性はありますか?そうすると、あらゆる種類の予期しないファンキーなことが起こる可能性があります。

于 2012-05-11T22:51:38.343 に答える