Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/119.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
objective-c带回调问题的损坏指针_Objective C_Ios_Pointers_Memory Management - Fatal编程技术网

objective-c带回调问题的损坏指针

objective-c带回调问题的损坏指针,objective-c,ios,pointers,memory-management,Objective C,Ios,Pointers,Memory Management,我遇到了一个在对象被释放后指向垃圾的坏指针的问题objectA是来自另一个对象的回调的委托,objectB objectA经常被分配和发布(在我的应用程序中,它是一个菜单UI对象)。每次初始化objectA时,它都会初始化objectB,并开始异步操作,然后通过id委托属性调用objectA。 如何阻止指针:id委托中断 ObjA.m -(void)dealloc{ [super dealloc]; } +(id)init{ ObjA *objectA = [[ObjA

我遇到了一个在对象被释放后指向垃圾的坏指针的问题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

}

这里的简短回答是,当您解除锁定objectA时,您可以
nil
out objectB的
delegate
属性。正如您所看到的,由于委托是分配的,而不是保留的(明确地防止保留循环),因此当“拥有”对象离开时,委托引用可能会挂起。通常,objectA将保留对objectB的引用,并且在objectA的
解除锁定
期间,它将首先将objectB的
委托
设置为
,然后
释放
objectB。这将防止撞车。当然,这假设(通常情况下)您不需要对异步完成做任何事情。它还假定ObjutB在安全操作的中间可以安全地被Objuta释放。这通常适用于(比如)动画,但如果您正在构建自己的任务,您可能需要注意这里的生命周期

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

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

  • 你在泄漏objectB。ObjectA创建了它(alloc,init),但随后删除了引用,所以即使完成了,似乎也没有人负责发布它。再一次,握住它,这样你就可以释放它,这也会解决这个问题

  • 对象上的
    -terminate
    是一种反模式——对象不应该(只有一个例外:
    init
    内部的故障)调用
    -release
    on
    self
    。对象应由其所有者(即最初创建它的人)释放

  • 您的
    if(self==[super init])
    模式通常是用一个等号编写的,这意味着您将
    self
    赋值给结果,并检查它是否为
    nil
    。这是一个历史上的怪事,在这里可能没有什么不同,但值得指出


  • 回答得很好!你知道有什么关于“反模式”或“模式”的正经读物吗?我从来没有想过[自我释放]可能是有害的。我需要按照您的建议合并一种保存引用的方法,或者我可以完全停止异步操作,这样它就不会回调。谢谢你的帮助!。Oliver@Oliver:您可以简单地将引用作为objectA上的实例变量或属性保存。很乐意帮忙。有一本名为《可可设计模式》的书,我认为这本书有点过火,但可能有助于你浏览一下。另外,如果你是新来的(或者真的,即使你不是),我喜欢亚伦·希尔莱加斯的书,因为它们清晰实用。