7

これは質問ではなく、iOS4および5のカメラ操作用にAppleが提供するAVCamサンプルコードの周りで私が見つけたものの記録です。私にとっての問題の症状は、約5〜10枚の写真を撮った後、AVCamViewControllerを起動するとアプリがクラッシュすることでした。

私はメモリリークプロファイラーを介してアプリを実行しましたが、明らかなリークはありませんでしたが、Activity Monitorで調べたところ、カメラを起動するたびにmediaserverdと呼ばれるものが17Mb増加し、100Mbに達するとアプリが複数の低でクラッシュしたことがわかりましたメモリ警告。

4

3 に答える 3

16

私が最初にしたことは、すべてのAVCamファイルのdeallocメソッドにログインすることでした。AVCamViewControllerが割り当て解除されていたときに、AVCamCaptureManagerとAVCamRecorderの割り当てが解除されていないことにすぐに気付きました。保持呼び出しと解放呼び出しを確認したところ、バランスが取れているように見えたので、[captureManagerリリース]にブレークポイントを設定し、リリース後にretainCountが2であることがわかりました(したがって、AVCamCaptureManagerのdeallocが呼び出されていませんでした)。

次に、キャプチャマネージャーの作成プロセスを実行したところ、initメソッドが呼び出された直後に保持カウントが3であることがわかりました。

initメソッドをステップ実行し、すべての行の保持カウントを確認すると、次の2つの行が両方とも保持カウントを増分していることがわかりました。

[self setDeviceConnectedObserver=[notificationCenter addObserverForName:AVCaptureDeviceWasConnectedNotification object:nil queue:nil usingBlock:deviceConnectedBlock]];
[self setDeviceDisconnectedObserver=[notificationCenter addObserverForName:AVCaptureDeviceWasDisconnectedNotification object:nil queue:nil usingBlock:deviceDisconnectedBlock]];

調べてみると、removeObserverの対応物がAVCamCaptureManagerのdeallocメソッド(呼び出されていなかった)の内部にあるため、保持カウントが0に低下することはありませんでした。

これを修正するために、新しいpublicremoveObserversメソッドを作成しました。

 -(void)removeObservers {
     NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
     [notificationCenter removeObserver:[self deviceConnectedObserver]];
     [notificationCenter removeObserver:[self deviceConnectedObserver]];
 }

そして、AVCamCaptureManagerdeallocメソッドから同じ行を取り出します。

[captureManagerremoveObservers]を呼び出します。次に、[captureManagerリリース]を呼び出します。AVCamViewControllerのdeallocメソッドでは、保持カウントが0に正常にドロップされます。

Activity Monitorを使用したテストでは、mediaserverdプロセスがわずか5〜17 Mbでハミングし、クラッシュが停止します。

これがこの問題を抱えている他の人に役立つことを願っています!

于 2011-10-25T01:45:38.013 に答える
4

Appleは2013年10月17日にサンプルコードを改訂し、保持サイクルを修正しました。この問題は、でself定義されたブロック内の不適切な使用が原因initです。

これがリビジョンの説明です

AVCaptureManagerリークが発生するリテンションサイクルを修正しました。AVCam-アプリでコードを適応させた場合は、ここで行われた修正をAVCaptureManager.minit方法で採用する必要があります。これらの修正がないと、AVCaptureManagerインスタンスがリークし、アプリがフォアグラウンドにある間、カメラが常に実行されたままになる可能性があります。


ただし、彼らが導入した修正は、手動保持カウントの場合にのみ機能します。プロジェクトでARCを使用している場合は、release/retain呼び出しやその他の明らかなものを取り除く以外に、のストレージ修飾子を次のようにからにweakSelf変更する必要があります。__block__weak

__weak AVCamCaptureManager *weakSelf = self;

実際、のセマンティクスは__blockARCで変更されました。MRCでは変数が弱く参照されていましたが、ARCでは参照されておらず、__weakこの目的で使用する必要があります。

このトピックの詳細については、こちらをご覧ください:APIを実装するときに、ブロック内で自分自身をキャプチャしないようにするにはどうすればよいですか?

init前回のリビジョンの新しい実装を使用し、の__weak代わりにを使用すると__block、最終的にdeallocメソッドが適切に呼び出されます。


最後に、古いレガシーコードを持ち歩くのが嫌いな人のために、AVCamプロジェクトの最新バージョンを示します:https ://github.com/Gabro/AVCam

特徴:

  • メモリリークが発生しない
  • ARCを使用
  • 最新のObjective-C構文
  • iOS7のマイナーなUI修正
于 2013-11-01T15:50:46.443 に答える
2

最近この問題に遭遇しました。本当の根本的な問題は、deviceConnectedBlockとdeviceDisconnectedBlockが暗黙的に自己を参照していて、保持サイクルにつながることであることがわかりました。これを修正するには、weakSelfを使用するようにそれらのブロック内のすべてのivar参照を変更します。

このように、ティアダウンメソッドを明示的に呼び出すことを覚えておく必要はありません。

これが他の誰かに役立つことを願っています。

REF:ARCでNSNotificationCenterコードブロックメソッドを使用すると、ビューコントローラーのdeallocが呼び出されない

于 2013-07-19T02:52:59.513 に答える