2012-02-01 11 views
4

StackOverflowには、私が持っているのと同じ問題を経験したいくつかの質問があります。しかし、彼らの解決策のどれもが私の場合に適合しませんでした。 (hereherehereと私は読んだが、役に立ったなかったSOの質問のいくつかのためにhereを参照してください。)UIButtonが起動してIBActionがARCでEXC_BAD_ACCESSを引き起こします

私の場合、私は、関連するコントローラのビューで、夫婦UIButton秒を持っているNIBを持っています。ビューは私のプロジェクトにとって比較的古く、今日までこれらのボタンを何の問題もなく使用することができました。ボタンの動作に関連しないコードをいくつか変更した後、私はアプリケーションをクラッシュさせてエラーに遭遇し、main()機能でコードを解読し、のボタンのいずれかが表示されたときにエラーメッセージEXC_BAD_ACCESSを返します。私のビューに。

これはどうやって起こりますか?私は実際にはほぼすべての機能コードをコメントアウトしました。特に、私が以前に修正したものはまだありましたが、エラーの発生を止めることはできません。

私のプロジェクトでは自動参照カウントが使用されていますが、このエラーは以前は表示されませんでした。さらに、NIBを変更したり、ボタンに関連付けられたIBActionも修正していなかったので、これが何を引き起こすのか分かりません。エラーを停止する唯一の方法は、コントローラビューのヘッダファイルに定義されているIBActionメソッドにNIBのUIButtonをリンク解除することです。

私のユースケースの唯一の「ユニークな」側面は、このビューの1つまたは2つのインスタンスを別のサブビューコントローラ内にロードすることです。ロードされた壊れたビューのインスタンスの数は、配列内のオブジェクトの数に依存します。以下は、これらのビューをインスタンス化して別のビューのサブビューとしてロードするために使用するコードです。

//Called else where, this starts the process by creating a view that 
//will load the problematic view as a sub-view either once or twice. 
- (id)initWithPrimarySystemView:(SystemViewController *)svc 
{ 
    //First we create our parent, container view. 
    self = [super initWithNibName:@"ContainerForViewInstaniatedFromArrayObjs" bundle:nil]; 
    if (self) 
    { 
     //Assign parent DataModel to local instance 
     [self setDataModel:((DataModelClass*)svc.DataModel)]; 
     for (AnotherModel* d in DataModel.ArrayOfAnotherModels) 
     { 
      //Instantiate the SubViewController. 
      SubViewController* subsvc = [[SubViewController alloc] 
              initWithNibName:@"Subview" 
              bundle:nil 
              subviewPosition:d.Position ]; 

      //Add the SubViewControllers view to this view. 
      [subsvc.view setFrame:CGRectMake((d.Position-1)*315, 0, 315, 400)]; 
      [self.view addSubview:subsvc.view]; 
     } 
     [self setDefaultFrame: CGRectMake(0, 0, 640, 400)]; 
    } 
    return self; 
} 

これは完璧に動作して、以前にも関連するビューにあったボタンを備えた任意のトラブルを起こしていなかったタップすると、しかし、今、すべてのUIButton sがアプリをクラッシュ。

SubViewControllerの初期化関数とviewDidLoadメソッドには、新しいViewControllerを作成するときに追加される標準の自動生成コード以外は何も含まれていません。

この問題を修正または診断するにはどうすればよいですか?

答えて

8

は、あなたのコード内で私のコメントを参照してください:

{ 
    SubViewController* subsvc = [[SubViewController alloc] initWithNibName:@"Subview" bundle:nil subviewPosition:d.Position ]; 
    //!i: By default, subsvc is a __strong pointer, so your subview has a +1 retain count 
    // subsvc owns subsvc.view, so subsvc.view has a +1 retain count as well 

    //Add the SubViewControllers view to this view. 
    [subsvc.view setFrame:CGRectMake((d.Position-1)*315, 0, 315, 400)]; 

    [self.view addSubview:subsvc.view]; 
    //!i: This bumps subsvc.view to +2, as self.view strong-references it 

    //!i: subsvc is going out of scope, so the reference count on subsvc will drop 
    // to 0 and it is dealloc'd. subsvc.view's retain count drops to +1, as it 
    // is still referenced by self.view 
    // 
    // Most likely, in -[SubViewController dealloc], you were not doing a 
    // setTarget:nil, setAction:nil on the button. Thus, the button now 
    // has a dangling pointer and will crash when hit 
} 

これを修正するには、マスター・ビューのcontrolerが所有する配列に各SubViewControllerインスタンスを追加します。これにより、SubViewControllerインスタンスがボタンタップを受け取るようになります。

+0

興味深いことに、私は私の机に着くときにこれを試してみましょう。私はこれがなぜ問題を解決するのか分かりますが、私はちょっと混乱しています。私はこのメカニズムを2週間ほどかかっています。私はそれに1つの問題はなかったし、調整したコードも関連するコードもなかった。あなたが言うことが問題であれば、これはいつも問題であったように思えます。これが特定の状況下ではうまくいくのかどうか分かりませんか? – RLH

+0

ありがとう、これは働いた! – RLH

+0

最近ARCにアップグレードしましたか?手動参照カウントではこれがリークのように見えます。 SubViewControllerを保持していて、タイマーを使用していた場合は実行ループ、アニメーション化していた場合はUIViewAnimationを保持することも可能です。 – iccir

1

を呼び出すあなたのdeallocで確認してください:

[ボタンremoveTarget:NULL forControlEvents: アクションnilをUIControlEventAllEvents]。

ARCで「dealloc」は必要ありませんが、iccirが説明した理由があります。

+0

これらのすべてのUIViewオブジェクトがIBで作成され、IBOutlets経由で接続されている場合は、これが必要ですか?私はこれを行う指示を読んだことはありません。 – RLH

+1

はい - 特にIBの場合。 IBは作成しますが、オブジェクトの破壊は処理しません。 – dacopenhagen

関連する問題