0

我在释放对象后指向垃圾的指针损坏时遇到问题。objectA是来自另一个对象objectB的回调的委托。
objectA经常被分配和释放(在我的应用程序中,它是一个菜单 UI 对象)。每次初始化objectA时,它都会初始化objectB并开始异步操作,然后通过 id 委托属性回调objectA 。如何阻止我的指针:id delegate 中断?

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 时,您将nil取出 objectB 的delegate属性。正如您所看到的,因为委托是分配的,而不是保留的(明确地防止保留循环),所以当“拥有”对象消失时,委托引用可能会挂起。通常 objectA 将持有对 objectB 的保留引用,并且在 objectA's 期间dealloc,它将首先将 objectB's 设置delegatenil,然后将releaseobjectB 设置为。这将防止崩溃。当然,这假设(通常)您不需要对异步完成做任何事情。它还假设 objectB 可以在 objectA 处于异步操作中间时安全地释放。这通常适用于(比如说)动画,但如果您正在构建自己的任务,您可能需要注意这里的生命周期。

有关此代码段的一些注释可能会有所帮助:

  1. 您的 objectA 在创建后实际上并没有持有对 objectB 的引用。这意味着您不能取消委托。您应该在创建 objectB 时保留对它的引用,以便执行此操作。

  2. 您正在泄漏 objectB。ObjectA 创建它(alloc,init),但随后删除引用,因此即使完成后,似乎也没有人负责释放它。同样,握住它以便您可以释放它也可以解决此问题。

  3. 您的-terminateon objectA 是一种反模式——一个对象永远不应该(只有一个例外:内部失败init)调用-releaseon self。一个对象应该由它的所有者释放,也就是最初创建的人。

  4. 您的模式if (self == [super init])通常用一个等号书写,这意味着您既要分配self结果又要检查nil. 这是 Cocoa 历史上的一个奇怪现象,在这里可能没有什么区别,但值得指出。

于 2012-09-03T14:37:20.337 回答