95

わかりました、これが契約です。デバッグやクラッシュについて質問するのは嫌いです。私は通常、それらを自分で処理するためですが、既に複数の質問を表示した後でも、これを回避することはできません

わかりましたので、ここに問題があります。このスタック トレースで、アプリがランダムにオンまたはオフにクラッシュすることがわかりました。

*** -[ViewController respondsToSelector:]: message sent to deallocated instance 0x1e5d2ef0

どこが変わる可能性がありますか、コードがクラッシュViewControllerする場所は、その特定のものとは関係がなく、それを所有または呼び出していません。ViewController

また、そのコンソール トレースを取得するために、Zombies を有効にしました。そうしないと、コンソール プリントがまったく取得されず、取得されるのは : だけですobjc_msgSend。これは、リリースされた何かをメッセージしていることを意味します。しかし、それがどこにあるのかわかりません...私は本当に立ち往生しています! 通常、私は常にクラッシュをデバッグするので、これに本当に行き詰まっています。

繰り返しますが、これはさまざまな場所でさまざまな時間に、オンとオフでクラッシュします。そして、それがクラッシュする場所は、 とはほとんど関係がありませんViewController。そして、これは非常に紛らわしいと思います。

私のコードが必要ですか?たくさんファイルがあり、さまざまな場所でクラッシュしているため、コードを配布するのは面倒です!

シンボリック ブレークポイントを追加しようとしましたが、うまくいきませんでした。iOS の Instruments アプリケーションでは Zombies を使用できません。サポートされていないアーキテクチャ フレームワークがあるため、シミュレーターでアプリを実行できません。

みんな、ありがとう...

4

7 に答える 7

169

Instrumentsを使用して、インスタンスの割り当て解除エラーを追跡します。アプリケーションのプロファイリング (Cmd ⌘</kbd>+I) and choose Zombies template. After your application is running, try to crash it. You should get something like that:

ここに画像の説明を入力

ポップオーバーのアドレスの横にある矢印をクリックして、割り当て解除後に呼び出されたオブジェクトを表示します。

ここに画像の説明を入力

このオブジェクトの保持カウントを変更したすべての呼び出しが表示されるはずです。これは、保持/解放メッセージを直接送信したり、自動解放プールを空にしたり、NSArray に挿入したりすることが原因である可能性があります。

RefCt列には、アクションが呼び出された後の保持カウントが表示され、 Responsible Callerには、アクションが実行されたクラス名とメソッドが表示されます。保持/解放をダブルクリックすると、インストゥルメントはこれが実行されたコード行を表示します (これが機能しない場合は、呼び出しを選択し、拡張詳細ペインで対応するものを選択して調べることができます)。

ここに画像の説明を入力

これにより、オブジェクトのretainCountライフサイクルをすべて調べることができ、おそらく問題をすぐに見つけることができます。あなたがしなければならないのは、最新リリースの保持の行方不明を見つけることです。

于 2012-06-23T16:12:51.520 に答える
59

同様の問題がありました。私の場合、viewController は navigationController イベントを取得する必要があったため、ナビゲーション コントローラー デリゲートとして登録していました。

 self.navigationController.delegate = self;

クラッシュは、コントローラーの割り当てが解除されたが、まだビュー コントローラーのデリゲートであった場合に発生します。このコードを dealloc に追加しても効果はありません。

-(void) dealloc
{
    if (self.navigationController.delegate == self)
    {
        self.navigationController.delegate = nil;
    }

dealloc が呼び出された時点で、View Controller は既にビュー階層から削除されているため、self.navigationController は nil であるため、比較は確実に失敗します。:-(

解決策は、このコードを追加して、VC がビュー階層を実際に離れる直前にそれを検出することでした。iOS 5 で導入されたメソッドを使用して、ビューがいつポップされ、プッシュされていないかを判断します

-(void) viewWillDisappear:(BOOL) animated
{  
   [super viewWillDisappear:animated];
   if ([self isMovingFromParentViewController])
   {
      if (self.navigationController.delegate == self)
      {
           self.navigationController.delegate = nil;
      }
   }
}

もうクラッシュしません!

于 2013-08-09T00:41:46.727 に答える
4

昨日、iOSで同じ問題に遭遇しました。アプリの「About」サブビューで IAP を作成し、「About」viewDidLoad に Transaction Observer を追加しました。初めて購入した時は問題なかったのですが、メイン画面に戻ってサブビューについて入力し直したら、「割り当て解除されたインスタンスにメッセージが送信されました」という問題が発生し、アプリがクラッシュしました。

- (void)viewDidLoad
{
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];                                           object:nil];
}

dealloc で Transaction Observer を削除すると、問題は解決しました。

- (void)dealloc
{
    // Even though we are using ARC, we still need to manually stop observing any
    // NSNotificationCenter notifications.  Otherwise we could get "zombie" crashes when
    // NSNotificationCenter tries to notify us after our -dealloc finished.

    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}
于 2015-03-25T03:50:55.467 に答える
4

非常によく似た問題があり、ナビゲーションコントローラーのデリゲートセットが原因であることがわかりました。

以下は私の問題を解決しました、

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    if (self.navigationController.delegate != self) {
        self.navigationController.delegate = self;
    }
}

-(void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];

    if (self.navigationController.delegate == self) {
        self.navigationController.delegate = nil;
    }
}
于 2015-07-01T05:42:20.747 に答える
4

それを解決できない人のために、他のテクニックをいくつか紹介します。

https://stackoverflow.com/a/12264647/539149

https://stackoverflow.com/a/5698635/539149

https://stackoverflow.com/a/9359792/539149

https://stackoverflow.com/a/15270549/539149

https://stackoverflow.com/a/12098735/539149

Xcode 5 でインストゥルメントを実行するには、プロジェクト ポップアップ -> [スキームの編集...プロファイル] -> [インストゥルメント] をクリックして [割り当て] または [リーク] を選択し、アプリをプロファイリングしてから [インストゥルメント] を停止し、[割り当て] の [情報] ボタンをクリックして [NSZombie 検出を有効にする] をクリックします。 .

ただし、com.apple.main-thread から直接送信されるメッセージの場合は、おそらく何も明らかになりません。

私はこれについて2時間以上頭を悩ませましたが、答えは過剰リリースであることが判明しました。これは、犯人が見つかるまで私のプロジェクトのコピーを力ずくでコメントアウトすることで発見しました。

[viewController release];
viewController = NULL;

問題は、リリースが変数を NULL に設定しないことです。

つまり、これを NULL 呼び出しに設定すると、再び解放され、refcount が減少し、後で viewController を参照する変数が終了するまですぐにメモリが解放されます。

そのため、ARC を有効にするか、プロジェクトで一貫してリリースまたは NULL を使用し、両方を使用しないようにしてください。私の好みは NULL を使用することです。これは、ゾンビを参照する可能性がないためですが、オブジェクトが解放された場所を見つけるのがより困難になります。

于 2013-10-08T00:30:42.727 に答える
2

私は同じ問題を抱えていました.行やコードステートメントを示していないため、どのデリゲートが問題を引き起こしているのかを見つけるのは困難でした.

  1. xib ファイルを開き、ファイルの所有者から、[接続インスペクターを表示] 右側のメニューを選択します。デリゲートがリストされ、疑わしいものは nil に設定します。
  2. (私の場合と同じ)Textfieldのようなプロパティオブジェクトは問題を引き起こす可能性があるため、デリゲートをnilに設定します。
-(void) viewWillDisappear:(BOOL) animated{

[super viewWillDisappear:animated];

if ([self isMovingFromParentViewController]){

self.countryTextField.delegate = nil;

self.stateTextField.delegate = nil;

}

}
于 2016-01-12T05:53:29.807 に答える
2

OS Xでも同じ問題がありました。

- (void)dealloc@SoftwareEvolvedがすでに述べたように、これを解決するには不十分な方法です。残念ながら- (void)viewWillDisappear、バージョン 10.10 以降でのみ使用できます。

すべてのゾンビ危険な参照を nil に設定するカスタム メソッドを NSViewController サブクラスに導入しました。私の場合、それはNSTableViewプロパティ(delegateおよびdataSource)でした。

- (void)shutdown
{
  self.tableView.delegate = nil;
  self.tableView.dataSource = nil;
}

それで全部です。スーパービューからビューを削除しようとするたびに、このメソッドを呼び出す必要があります。

于 2014-12-09T15:05:23.833 に答える