如何避免将回调发送到解除分配的实例

时间:2010-10-29 12:15:47

标签: iphone delegates callback calendar dealloc

以下过程会导致我的应用崩溃:

  • 用户打开视图并将请求发送到服务器
  • 请求在后台执行
  • 用户导航回根视图
  • 请求已完成

并执行以下代码

// MyDatasource.m  
// e.g. in connectionDidFinishLoading  
[callback loadedDataSource:self];

与此同时,其他模型/视图已被解除分配,并且消息将被发送到解除分配的实例。

callback的类型为id,符合KalDataSourceCallbacks协议。

如何避免将消息发送到解除分配的对象?

PS:我的问题类似于this question

修改

我将尝试在callback方法(在我的数据源类中)中将dealloc设置为nil。这并不能解决问题,因为MyDataSource始终存在,dealloc方法只有在释放RootViewController时才会被调用(应用程序关闭时会发生什么)。

到目前为止我做了什么:

现在MyDataSource中的属性保留了RootViewController

// RootViewController.h
@property (retain) MyDataSource *dataSource;

// RootViewController.m
@synthesize dataSource;
// ...
self.dataSource = [[[MyDataSource alloc] init] autorelease];
kal.dataSource = dataSource;

- (void)dealloc {
    [dataSource release];
    // ...
}
  

KalViewController不保留其数据源。您可能希望在实例变量中存储对dataSource的引用,以便在日历被销毁后释放它。

我还创建了一个callback属性:

// MyDataSource.h
@property (retain) id<KalDataSourceCallbacks> callback;

// MyDataSource.m
@synthesize callback;
// ...
- (void)presentingDatesFrom:(NSDate *)fromDate to:(NSDate *)toDate delegate:(id<KalDataSourceCallbacks>)delegate {
    // ...
    self.callback = delegate;
}
- (void)dealloc {
[callback release];
callback = nil;
   // ...
}

目前该应用未崩溃。我必须在设备上进行测试。添加callback = nil在这里没有做任何事情,因为从不调用dealloc。

在日历被销毁后我应该如何发布MyDataSource?这不起作用,因为我不知道日历是否已被销毁。因此,dataSource只能在整个应用程序运行时间内生存。

编辑2:

我可以查看callback nil以查看它是否已被释放?

if (callback != nil)
     [callback loadedDataSource:self];

这没有帮助。

编辑3:

应用程序没有崩溃,因为我保留了委托:

@property (retain) id<KalDataSourceCallbacks> callback;

应该是

@property (assign) id<KalDataSourceCallbacks> callback;

那么我怎么能避免将方法loadedDataSource发送到我的特殊情况的解除分配对象?

3 个答案:

答案 0 :(得分:1)

当您离开当前视图时,将委托设置为nil。

答案 1 :(得分:0)

您需要确保完成连接并将其释放并将其设置为nil。 发送到nil对象的消息将被忽略。

答案 2 :(得分:0)

KalDataSource.h中,我将以下方法添加到KalDataSource协议:

@protocol KalDataSource <NSObject, UITableViewDataSource>
    // ...
    - (void)destroyCallback;
@end

KalDataSource.m中,我添加了删除警告的方法:

@implementation SimpleKalDataSource
// ...
- (void)destroyCallback
{
    // do nothing
}
@end

KalViewController.m中,当取消分配对象时,我正在调用我之前创建的方法:

- (void)dealloc
{
    // ...
    [dataSource destroyCallback];
}

MyDataSource.m我正在实施功能

- (void)destroyCallback {
    self.callback = nil;
}

并将委托设置为nil。