开发者

how to avoid that callback is sent to deallocated instance

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,开发者_C百科 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?


when you move out of the current view set the delegate to nil.


You will need to make sure that you finish the connection and release it and set it to nil. A message sent to a nil object is ignored.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜