19

すべてのページデータをキャッシュするUIPageViewControllerのXcodeのテンプレートが原因でメモリの問題が発生したため、ページを動的にロードするように変更しました。これで、アプリがメモリ不足の警告を受け取ると、ページが表示されないようにメモリが解放されます。ユーザーが画面の端をタップすることでページをすばやくめくっていますが、それでもクラッシュします。これは、didReceiveMemoryWarningが呼び出されたときにメモリを十分に速く解放できないためだと思います。ユーザーがゆっくりと弾いている場合は、正常に機能します。ユーザーがページをめくる速度を制限しましたが、それでも発生します。ページがめくられるたびにメモリを解放できるようにし、メモリ不足の警告を待つ必要がないようにしたい。ARCを使用しています。これを行う方法はありますか?または、これを防ぐために他に何ができますか?ありがとう。

編集:

(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
    NSUInteger index = [self indexOfViewController:(SinglePageViewControllerSuperclass *)viewController];
    if ((index == 0) || (index == NSNotFound)) {
        return nil;
    }

    index--;
    return [self viewControllerAtIndex:index];
} 

(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
    NSUInteger index = [self indexOfViewController:(SinglePageViewControllerSuperclass *)viewController];
    if (index == NSNotFound || index == MAX_PAGE_INDEX) {
        return nil;
    }

    return [self viewControllerAtIndex:++index];
}
4

5 に答える 5

5

私も同様の動作を経験したので、あなたの仮説は正しいと思います。次のページに移動すると、アニメーションをうまく行うためにも、古いページの割り当てが解除される前に新しいページが割り当てられ、割り当てを解除する古いもの。したがって、十分に速く反転すると、オブジェクトは割り当て解除よりも速く割り当てられ、最終的に(実際には、すぐに)、メモリ使用量のためにアプリが強制終了されます。のメモリの割り当て/割り当て解除に従うと、ページをめくるときの割り当て解除の遅延が非常に明白になりますInstruments

これには、IMOという3つのアプローチがあります。

  1. 「軽い」viewDidLoad方法(実際には、初期化/初期表示シーケンス全体)を実装します。一部のアプリでは、たとえば、表示される高解像度画像の代わりに低解像度画像をロードするのが理にかなっています。または、ページに必要な追加リソース(dbアクセス、サウンドなど)の割り当てをわずかに遅らせます。

  2. ページのプール、たとえば3ページの配列(または5、アプリによって異なります)を使用して、アプリのメモリプロファイルを安定させ、スパイクを回避するために「再利用」を続けます。

  3. メモリの割り当てと解放の方法を注意深く確認してください。この意味で、自動解放によって解放/割り当て解除メカニズムに「慣性」が追加されることをよく読んでいます。これは非常に理解しやすいものです。自動解放されたオブジェクトがある場合、そのオブジェクトは、循環するときにのみ解放プールによって解放されます。メインループ(これはメインリリースプールに当てはまります)。したがって、ページをめくるときに呼び出されるメソッドのシーケンスが長い場合、これによりリリース/割り当て解除が後で発生します。

メモリ使用量の最適化に関しては、特効薬はありません。非常に詳細で大変な作業ですが、コードを確認してこれら3つのガイドラインを適用すると、アプリのメモリプロファイルを減らすことができます。特に、Instrumentsのメモリ割り当ての急増を検査し、それらが何に関連しているかを理解しようとすることは非常に強力です。

于 2012-05-31T13:56:04.817 に答える
2

これが私が行った追加の変更であり、誰かが役立つと思うかもしれません:

基本的に、前のページが終了した場合にのみ、新しいページのめくりを開始できます。

AppleのデフォルトのPageViewControllerプロジェクトをテンプレートとして使用しているので、そのプロジェクトで定義されている用語を使用します。

shouldDenyVCviewControllerAtIndex:を介してページVCが要求されるたびに、' 'というブール値をModelControllerに設定しYESます。

UIPageViewControllerのデリゲートであるEbookViewControllerで、ジェスチャレコグナイザーをキャプチャし、EbookViewControllerをデリゲートとして割り当てます。

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

次に、ジェスチャ認識機能を拒否することで、ページめくりを拒否できます。

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:    (UITouch *)touch
{
    if (_modelController.shouldDenyPageTurn == YES) {
        return FALSE;
    }
    return TRUE;
}

そして最後に_modelController.shouldDenyPageTurn = NO、UIPageViewControllerデリゲートメソッドの最後に設定しましたpageViewController:didFinishAnimating:previousViewControllers:transitionCompleted:

_modelController.shouldDenyPageTurn = NOまた、ページめくりがすぐにできるように、プリロードの最後に設定する必要がありました。

于 2012-09-28T17:37:22.313 に答える
0

現時点でiOS5にバグがあり、スクロールビューで少量のメモリがリークします。

割り当てとメモリリークをチェックする機器でアプリケーションのプロファイリングを試みましたか?

シミュレーターのいずれかで低メモリー警告をシミュレートできます(ハードウェア->低メモリー警告のシミュレーション)。または、コードを介して実行することもできます(これにより、アプリが拒否されるため、デバッグ後に削除することを忘れないでください!)

[[UIApplication sharedApplication] performSelector:@selector(_performMemoryWarning)];

strongまたはretainプロパティを使用している場合は、それらを使いnil終わった後でそれらを設定すると、ARCはそれらが舞台裏で指しているメモリを解放します。

多数の一時オブジェクト(プロパティではない、または割り当てられていないオブジェクト)を作成している場合は、自動解放プールを挿入します。

@autoreleasepool {

}

そして最後に、いくつかのコードを示してください。

于 2012-05-28T01:41:53.770 に答える
0

コードを投稿しなかったので、問題がどこにあるのかを正確に推測するのは困難です。

  1. ビューを強制的にアンロードするには、に表示viewDidDisappear:されているviewcontrollerクラスのメソッドをオーバーライドできますUIPageViewController

    コードは次のようになります。

    - (void)viewDidDisappear:(BOOL)animated {
        [self didReceiveMemoryWarning];
    }
    

    また、didReceiveMemoryWarningをオーバーライドしている場合は、そこから呼び出すことを忘れないでください[super didReceiveMemoryWarning];

  2. また、UIPageViewControllerDataSourceメソッドがどのように機能するかについて混乱が生じる可能性があります。「そこに混合ワイヤがある」場合があります。ここで受け入れられた答えを確認してください。

于 2012-06-02T16:45:10.807 に答える
0

レンダリングが原因である可能性があります。フリッパーが速すぎると、「ページ」の再描画によって使用されるメモリとCPUが急速に増加します。UIPageViewControllerで使用したビューがCALayerに基づいており、ページ数が多すぎる場合、めくりが速すぎるとアプリが確実にクラッシュします。

1つの解決策は、レイヤーをカスタマイズしてレンダリング結果をキャッシュすることです。必要な場合にのみコンテンツを再レンダリングします。ただし、キャッシュによってメモリ使用量が増える可能性があります。

于 2012-07-19T08:38:39.433 に答える