如何避免回调被发送到释放实例 [英] how to avoid that callback is sent to deallocated instance
问题描述
以下过程导致我的应用崩溃:
- 用户打开一个视图,请求发送到服务器
- 请求在后台执行
- 用户导航回根视图
- 完成
并执行以下代码
// MyDatasource.m
// eg in connectionDidFinishLoading
[callback loadedDataSource:self];
同时,其他模型/视图已被释放,并将消息发送到释放实例。
回调
的类型为 id
,符合 KalDataSourceCallbacks
protocol1。
如何避免将消息发送到已释放对象?
PS:我的问题类似于这个问题
编辑:
callloc
方法(在我的datasource类中)的回调
到nil。这不解决问题,因为 MyDataSource
总是存在,并且 dealloc
方法应该只调用 RootViewController
已发布(当应用关闭时会发生什么)。
到目前为止, p>
现在 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的引用,以便在日历被销毁后可以释放它。
我还创建了一个回调
属性:
// MyDataSource.h
@property(retain)id< KalDataSourceCallbacks>回电话;
// 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:
我可以为 nil
检查回拨
以确定是否已发布?
if(callback!= nil)
[callback loadedDataSource:self];
这没有帮助。
编辑3:
应用程式并未崩溃,因为我保留了委派:
@property(retain)id< KalDataSourceCallbacks>回电话;
应为
@property(assign)id< KalDataSourceCallbacks>回电话;
那么如何避免方法 loadedDataSource
KalDataSource.h $
c $ c>我添加了以下方法到
KalDataSource
protocol1: @protocol KalDataSource< NSObject,UITableViewDataSource>
// ...
- (void)destroyCallback;
@end
在 KalDataSource.m
我添加了方法以摆脱警告:
@implementation SimpleKalDataSource
// ...
- (void)destroyCallback
{
// do nothing
}
@end
在 KalViewController.m
当对象被释放时,我在调用我的create方法之前:
- (void)dealloc
{
// ...
[dataSource destroyCallback];
}
在 MyDataSource.m
我正在实现函数
- (void)destroyCallback {
self.callback = nil;
}
并将委托设置为nil。
The following process leads to a crash of my app:
- the user opens a view and a request is send to the server
- the request is executed in background
- the user navigates back to the root view
- the request has been finished
and the following code is executed
// MyDatasource.m
// e.g. in connectionDidFinishLoading
[callback loadedDataSource:self];
In the meantime the other models/views has been deallocated and the message is sent to a deallocated instance.
callback
is of type id
and conforms to the KalDataSourceCallbacks
protocoll.
How can I avoid that a message is sent to a deallocated object?
PS: My question is similar to this question
Edit:
I'll try to set callback
to nil in the dealloc
method (in my datasource class). This doesn't solve the problem, because MyDataSource
is always present and the dealloc
method should only be called if RootViewController
is released (what should happen when the app is closed).
What I've done so far:
Now MyDataSource
is retained by a property in my 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 does not retain its datasource. You probably will want to store a reference to the dataSource in an instance variable so that you can release it after the calendar has been destroyed.
I also created a callback
property:
// 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;
// ...
}
Currently the app is not crashing. I have to test on the devices. Adding callback = nil
doesn't do anything here, because the dealloc is never called.
How should I release MyDataSource
after the calendar has been destroyed? That doesn't work because I don't know if the calendar has been destroyed. So the dataSource can only live over the whole app runtime.
Edit 2:
Can I check callback
for nil
to find out if it has been released?
if (callback != nil)
[callback loadedDataSource:self];
This doesn't help.
Edit 3:
The app was not crashing because I retained the delegate:
@property (retain) id<KalDataSourceCallbacks> callback;
should be
@property (assign) id<KalDataSourceCallbacks> callback;
So how could I avoid that the method loadedDataSource
is sent to a deallocated object for my special case?
In KalDataSource.h
I added the following method to the KalDataSource
protocoll:
@protocol KalDataSource <NSObject, UITableViewDataSource>
// ...
- (void)destroyCallback;
@end
In KalDataSource.m
I added the method to get rid of the warnings:
@implementation SimpleKalDataSource
// ...
- (void)destroyCallback
{
// do nothing
}
@end
In KalViewController.m
I'm calling my before created method when the object is deallocated:
- (void)dealloc
{
// ...
[dataSource destroyCallback];
}
In MyDataSource.m
I'm implementing the function
- (void)destroyCallback {
self.callback = nil;
}
and set the delegate to nil.
这篇关于如何避免回调被发送到释放实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!