2017-04-21 13 views
0

私のアプリは標準のUINavigationViewControllerを使用しています。UINavigationViewControllerの重いSceneKitシーンがdeallocに時間がかかりすぎます

ユーザは、ある時点で、SceneKitシーンを示すViewControllerにナビゲートしています。

このシーンは約6000のジオメトリを持ち、各ジオメトリには独自のマテリアルがあるため(このようにする必要があります)、非常に重いメモリです。

前のviewControllerに戻るためにユーザーがトップバーの戻るボタンをクリックすると、アプリケーションは現在のView Controllerを正しくポップし、下のものを表示します。

しかし、約4秒間、表示された新しいViewControllerのUIがフリーズします。

私は楽器時間プロファイラを使用している、と私はそれらの4秒の大部分は、これらのSceneKit方法によって取られていることを見ることができます:

- [NSConcreteMapTable countByEnumeratingWithState:オブジェクト:カウント:]

- [SCNMetalResourceManager _geometryWillDie:]

- [SCNMetalResourceManager _materialWillDie:]

ように多くの幾何学的形状や材料があるので、それは理にかなっています。

SceneKitのパースペクティブ(解除が速くなる)またはUINavigationViewControllerのパースペクティブ(多分シーンが発生するのを強制的に強制する)のどちらかで、重いシーンが解放されている間にUIがブロックされないように、別のスレッド?)。

答えて

0

私の理解では、SceneKitは自分自身のバックグラウンドスレッドを使用して作業するので、メインスレッドをブロックしてはいけません。

メインスレッドのブロックは、内容をアニメーション化するUINavigationControllerと関係している可能性があります。私はSCNViews/SCNScenesをアニメーション化しようとするときに問題があり、SceneKitとCoreAnimationが非常によくコラボレーションしないように見えます。私はここで完全なコンテキストを持っていないが、私はテストにあなたのために物事のカップルを提案することができます

  1. あなたはに重いシーンscnView.scene = [SCNScene scene];とSCNViewのシーンproperyを設定してみてくださいすることができますシーンがあるView Controllerの直前にある新しい空のシーンがポップオフされるため、重いシーンはアニメーションに含まれず、SceneKitはバックグラウンドの脅威に適切に割り当てを解除します。

  2. ビューコントローラの重いシーンを強く参照すると、重いシーンで問題のあるView Controllerを準備することができます。

    その後、後者がポップオフされ、その下のものに戻ると、View Controllerがポップされ、重いシーン以外のすべてのコンテンツが割り当て解除されている必要があります。

    ここではアニメーションが完了した後にnilに設定してみることもできますが、SceneKitのバックグラウンドスレッドで適切に割り当てを解除することもできます。

    ない場合は、まずすべてのheavyScene.rootNodeの子ノード、アクション、などを削除して割り当てを解除することができます。

    これはまだ動作しない場合は、まず、すべてのノードを一つずつを横断する再帰関数を使って試してみて、その幾何学/材料nilの最初と、シーン自体の割り当てを解除することができます。 (秒未満)は、いくつかのフレームにわたってノードを削除するレンダリングループ-renderer:updateAtTime:方法を使用

  3. 。そうすれば、SceneKitが設計された方法でそれらを処理することができます。

    ユーザーがUINavigationController「戻るボタン」を押すと重いシーンでのVCがポップされているときを検出する必要があります。その後、20フレーム(60fpsで1/3秒)を超えて、各フレームでノードの5%を削除します。したがって、わずかな遅延がありますが、1/3秒です。

    VCがポップオフされるのを検出するには、didMoveToParentViewController:メソッドをオーバーライドし、nilparentパラメータとして渡されているかどうかをチェックすることで発生する可能性があります。

たとえば、あなたの答えのための

- (void)didMoveToParentViewController:(UIViewController *)parent { 

    if (!parent) { 
     // work that should be done when VC is being removed from parent 
     // maybe set a counter in the VC being popped off to 
     // count down from 20 to 0, -1 at each -update call 
    } 
} 
+0

感謝。私はオプション1を試しましたが、何が起こるかは、4秒間のUIのフリーズが、ポップ・オフ・アニメーションの後ではなく、その前に起こるということです。つまり、コンテンツのUIAnimationControllerアニメーションとは関係がないようです。私はまた、現在のViewControllerから離れずに重いシーンを新しい空のシーンに設定しようとしましたが、UIもブロックされます。だから私はどうにかして主スレッド上で割り振り解除が起こっていると思う。また、私は "enumerateObjectsUsingBlock"を使用して、すべてのノードのジオメトリをゼロにして、UIもブロックしてみました。 –

+0

他のオプションを試しましたか?重いシーンへの参照を保持して、直前のView Controllerに行くときに直ちに割り当てを解除しないようにしました。移行が完了した後でのみ、バックグラウンドスレッドにnilに設定します。私はまた、より現実的な新しいソリューションを追加しました。上記の答えで**オプション3 **を参照してください。 – Sulevus

+0

こんにちは@Sulevus、はい、前のView Controllerの重いシーンへの参照を維持するのはやりました。あなたの答えに多くの感謝! –

関連する問題