Управление памятью с помощью ARC на iOS - PullRequest
0 голосов
/ 18 февраля 2012

Просто быстро задайте вопрос (скорее из любопытства), основанный на проблеме, которую я только что решил (я опубликую ответ на мою проблему в посте, который можно найти здесь: Мой прежний вопрос

Дело в том, что у меня есть этот UITableView, который содержит пользовательские объекты ячейки. Каждый раз, когда вы входите в это представление, я генерирую новые ячейки для UITableView следующим образом:

    if (cell == nil)
{
    [[NSBundle mainBundle] loadNibNamed:@"UploadCellView" owner:self options:nil];

    cell = customCell;
}

Что происходит стандартным методом:

-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

Теперь проблема в том, что мои пользовательские объекты ячеек прослушивают NSNotification о загружаемых объектах, происходящих в фоновом режиме, поэтому они могут обновить данные своей модели до своих меток и индикаторов выполнения и т. Д. клеточные объекты):

-(void) uploadProgress: (NSNotification*)notification
{
NSDictionary *userInfo = [notification userInfo];

NSNumber *uploadID = [userInfo valueForKey:@"uploadID"];

if (uploadID.integerValue == uploadActivity.uploadID)
{
    UIProgressView *theProgressBar = (UIProgressView*)[self viewWithTag:progressBarTag];

    [theProgressBar setProgress:(uploadActivity.percentageDone / 100) animated:YES];

    UILabel *statusText = (UILabel*)[self viewWithTag:percentageTag];

    [statusText setText:[NSString stringWithFormat:@"Uploader - %.f%% (%.01fMB ud af %.01fMB)", uploadActivity.percentageDone, uploadActivity.totalMBUploaded, uploadActivity.totalMBToUpload]];
}
}

Когда загрузка заканчивается, они просто делают это:

-(void) uploadFinished: (NSNotification*)notification
{
NSDictionary *userInfo = [notification userInfo];

NSNumber *uploadID = [userInfo valueForKey:@"uploadID"];

if (uploadID.integerValue == uploadActivity.uploadID)
{        
    [self setUploadComplete];

    [[ApplicationActivities getSharedActivities] markUploadAsFinished:uploadActivity];

    NSLog(@"BEGINNING RELOAD");
    [parentTable reloadData];
    NSLog(@"ENDING RELOAD");
}
}

Теперь проблема в том, когда они вызывают свой собственный просмотр таблицы. Когда представление, которое содержится в представлении таблицы, закрывается, старые пользовательские объекты ячеек все еще живут в фоновом режиме и получают NSNotfications. И когда эта загрузка будет выполнена, старые пользовательские объекты ячеек из прежних табличных представлений все еще пытаются вызвать свойство parentTable, которое было установлено в то время, что теперь приводит к вызову случайной ненужной памяти.

Способ, которым я решил это, состоял в том, чтобы сохранить массив всех объектов ячеек, создаваемых в таблице, и затем заставить их перестать слушать, когда представление отклоняется следующим образом:

-(void) viewWillDisappear:(BOOL)animated
{
    for (UploadCell *aCell in lol)
    {
        [aCell stopListening];
    }

    [self.navigationController popViewControllerAnimated:YES];
}

Но это похоже на взлом. Как бы я мог убедиться, что пользовательские объекты ячеек удаляются при закрытии представления? Потому что, когда представление снова инициализируется, новые ячейки просто создаются в любом случае, поэтому я не буду использовать старые.

У пользовательских ячеек представления есть сильный указатель свойства на табличное представление, с которым они связаны, но я думал, что ARC удостоверится, что указатель TableView не станет недействительным тогда? Очевидно, это так или иначе. Может быть, из-за удаления содержащего представления при извлечении?

Ответы [ 2 ]

1 голос
/ 18 февраля 2012

Похоже, что у ячеек есть свойство retain, указывающее на ваш класс UITableViewDataSource.

Вместо этого они должны иметь свойство назначить, тогда они будут освобождены должным образом, когда будет выпущено табличное представление (которое в настоящее время не может бытьесли ваши ячейки сохраняют его).

Кроме того, ячейки должны закрывать уведомления, когда они выпадают из таблицы, переопределяя ячейки didMoveToSuperview метод:

- (void)didMoveToSuperview
{
    [super didMoveToSuperview];
    if ( [self superview] == nil )
    {
        [self unsubscribeFromYourNotifications];
    }
}

Тотак что, если они прокрутят экран, они не будут тратить ресурсы на обновление вещей.

0 голосов
/ 18 февраля 2012

Рассматривали ли вы отдельную модель обновления, которая хранит карту между uploadID и ячейками, которые прослушивают уведомление?Таким образом, ячейки не несут ответственности за обновление таблицы сами, модель обновления сделает это.Когда таблица исчезнет, ​​вы можете завершить обновление модели.

...