как избежать обратного вызова в освобожденный экземпляр - PullRequest
0 голосов
/ 29 октября 2010

Следующий процесс приводит к сбою моего приложения:

  • пользователь открывает представление и отправляет запрос на сервер
  • запрос выполняется в фоновом режиме
  • пользователь переходит обратно к корневому представлению
  • запрос завершен

и выполняется следующий код

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

Тем временемдругие модели / виды были освобождены, и сообщение отправлено в освобожденный экземпляр.

callback имеет тип id и соответствует протоколу KalDataSourceCallbacks.

Как можноЯ избегаю отправки сообщения на освобожденный объект?

PS: мой вопрос похож на этот вопрос

Редактировать:

Я попытаюсь установить callback равным nil в методе dealloc (в моем классе источника данных).Это не решает проблему, потому что 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 не сохраняет свой источник данных.Возможно, вы захотите сохранить ссылку на источник данных в переменной экземпляра, чтобы вы могли освободить ее после уничтожения календаря.

Я также создал свойство 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 после того, как календарь был уничтожен?Это не работает, потому что я не знаю, был ли уничтожен календарь.Таким образом, источник данных может существовать только в течение всего времени выполнения приложения.

Изменить 2:

Могу ли я проверить callback для nil, чтобы выяснить, было ли оновыпущен?

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

Это не помогает.

Редактировать 3:

Приложение не зависало, потому что я сохранил делегата:

@property (retain) id<KalDataSourceCallbacks> callback;

должно быть

@property (assign) id<KalDataSourceCallbacks> callback;

Так как же мне избежать, чтобы метод loadedDataSource отправлялся в освобожденный объект для моего особого случая?

Ответы [ 3 ]

1 голос
/ 29 октября 2010

при выходе из текущего представления установите делегата на ноль.

0 голосов
/ 29 октября 2010

В 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;
}

и установите делегата на ноль.

0 голосов
/ 29 октября 2010

Вам нужно будет убедиться, что вы закончили соединение, отпустите его и установите ноль. Сообщение, отправленное нулевому объекту, игнорируется.

...