0

オブジェクトが解放された後、ガベージを指している壊れたポインタに問題があります。objectAは、別のオブジェクトobjectBからのコールバックのデリゲートです。
objectAは頻繁に割り当てられ、解放されます(私のアプリケーションでは、メニューUIオブジェクトです)。objectAが初期化されるたびに、objectBが初期化され、非同期操作が開始されてから、idデリゲートプロパティを介してobjectAにコールバックされます。ポインタを停止するにはどうすればよいですか:idデリゲートが壊れることはありませんか?

ObjA.m
-(void)dealloc{
     [super dealloc];
} 

+(id)init{
     ObjA *objectA = [[ObjA alloc]init];
     return objectA;
}
-(id)init{
     if (self == [super init]){
         ObjB *objectB = [ObjB initialiseWithDelegate:self];

     }
     return self;
}    
-(void)callback:(id)arg{
     //This callback is called from an asynchronous routine from  objectB 

}
-(void)terminate{
  //This is called when I want to remove/release objectA
  //Other logical termination code here
  [self release];
}


ObjB.m
@synthesize delegate;

+(id)initialiseWithDelegate:(id)delegate{
     ObjB *objectB = [[ObjB alloc]init];
     [objectB setDelegate:delegate];
     return objectB;
}
-(id)init{
     if (self == [super init]){
         [self beginAsynchronousOperation];

     }
     return self;
}
-(void)beginAsynchronousOperation{
     //Do asynchronous stuff here
}
-(void)finishedAsynchronousOperation{
     //Called when asynch operation is complete

     if (self.delegate) [self.delegate callback:someargument]; //EXC error. Pointer broke

}
4

1 に答える 1

1

ここでの簡単な答えは、 objectAをdeallocするときにnilobjectBのdelegateプロパティを削除することです。デリゲートは割り当てられており、保持されていないため(保持サイクルを防ぐために明示的に)、これまで見てきたように、「所有」オブジェクトがなくなったときにデリゲート参照をぶら下げたままにすることができます。通常、objectAはobjectBへの保持された参照を保持し、objectAの間にdealloc、最初にobjectBをに設定delegatenil、次にreleaseobjectBを設定します。これにより、クラッシュを防ぐことができます。もちろん、これは(通常のように)あなたが必要としないことを前提としていますその非同期完了で何かをするために。また、objectBが非同期操作の途中である場合、objectAによって安全に解放できることも前提としています。これは通常、(たとえば)アニメーションに当てはまりますが、独自のタスクを作成する場合は、ここでの存続期間に注意する必要がある場合があります。

このコードスニペットに関するいくつかの注意事項が役立つ場合があります。

  1. objectAは、作成された後、objectBへの参照を実際には保持していません。これは、デリゲートを無効にすることができないことを意味します。これを行うことができるように、作成時にobjectBへの参照を保持する必要があります。

  2. objectBをリークしています。ObjectAはそれを作成します(alloc、init)が、その後参照を削除するため、それが完了した場合でも、誰もそれを解放する責任を負わないようです。繰り返しますが、リリースできるように保持すると、これも修正されます。

  3. on objectA-terminateはアンチパターンです。オブジェクトは(1つの例外を除いて、内部の失敗init)を呼び出すこと-releaseはできませんselfオブジェクトは、最初に作成した所有者が解放する必要があります。

  4. のパターンif (self == [super init])は通常、1つの等号で記述されます。つまり、結果に割り当てるselfだけでなく、結果をチェックすることもできますnil。これはココアの歴史的な奇妙さであり、おそらくここでは違いはありませんが、指摘する価値があります。

于 2012-09-03T14:37:20.337 に答える