обновление ячейки представления таблицы пользовательского интерфейса со статусом загрузки - iOS

К черту всех :)

Мой опыт работы с контроллером UITablewView в iOS, к сожалению, весьма ограничен. В моем приложении мне нужно представление таблицы пользовательского интерфейса, которое содержит одну настраиваемую ячейку для каждой активной загрузки, загружаемой в данный момент на веб-сервер (видео, аудио и т. д.).

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

Теперь я нашел решение, которое работает. Проблема в том, что я не знаю, действительно ли это безопасно или нет. Основываясь на своем собственном выводе, я действительно не думаю, что это так. Что я делаю, так это просто извлекаю ссылку на UIViews из создаваемой ячейки, а затем сохраняю эти ссылки в загружаемых объектах, чтобы они могли сами изменять текст метки и так далее.

Мое собственное решение

-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
 static NSString *CustomCellIdentifier = @"CustomCell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CustomCellIdentifier];

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

    if ([nib count] > 0)
    {
        cell = customCell;
    }
    else
    {
        NSLog(@"Failed to load CustomCell nib file!");
    }
}

NSUInteger row = [indexPath row];
UploadActivity *tempActivity = [[[ApplicationActivities getSharedActivities] getActiveUploads] objectAtIndex:row];

UILabel *cellTitleLabel = (UILabel*)[cell viewWithTag:titleTag];
cellTitleLabel.text = tempActivity.title;

UIProgressView *progressbar = (UIProgressView*)[cell viewWithTag:progressBarTag];
[progressbar setProgress:(tempActivity.percentageDone / 100) animated:YES];

UILabel *cellStatusLabel = (UILabel*)[cell viewWithTag:percentageTag];

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

tempActivity.referencingProgressBar = progressbar;
tempActivity.referencingStatusTextLabel = cellStatusLabel;

return cell;
}

Как видите, здесь я думаю, что делаю что-то недостаточно хорошее: tempActivity.referenceProgressBar = progressbar; tempActivity.referenceStatusTextLabel = cellStatusLabel;

Действия загрузки получают ссылку на элементы управления, хранящиеся в этой ячейке, и затем могут обновлять их самостоятельно. Проблема в том, что я не знаю, безопасно это или нет. Что, если ячейка, на которую они ссылаются, будет повторно использована или удалена из памяти и т. д.?

Есть ли другой способ, которым вы можете просто обновить базовую модель (мои действия по загрузке), а затем заставить табличное представление пользовательского интерфейса перерисовать измененные ячейки? Не могли бы вы в конечном итоге создать подкласс UITableViewCell и позволить им постоянно проверять загрузку, а затем заставлять их загружать себя?

ИЗМЕНИТЬ

Вот как объекты активности загрузки вызывают свои ссылающиеся элементы пользовательского интерфейса:

- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten
totalBytesWritten:(NSInteger)totalBytesWritten
totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
{
if (referencingProgressBar != nil)
{
    [referencingProgressBar setProgress:(percentageDone / 100) animated:YES];
}

if (referencingStatusTextLabel != nil)
{
    [referencingStatusTextLabel setText:[NSString stringWithFormat:@"Uploader - %.f%% (%.01fMB ud af %.01fMB)", percentageDone, totalMBUploaded, totalMBToUpload]];
}
}

Меня беспокоит только то, что, поскольку эти объекты работают асинхронно, что, если в какой-то момент табличное представление пользовательского интерфейса решит удалить или повторно использовать ячейки, на которые указывают эти загружаемые объекты? Это не кажется очень безопасным вообще.


person CodingBeagle    schedule 16.02.2012    source источник
comment
Здравствуйте~ Я хочу использовать ApplicationActivities. Но я не могу знать, что я добавляю framework. Пожалуйста, расскажите мне об этом. :-0 Спасибо!   -  person hyekyung    schedule 19.06.2012
comment
ApplicationActivities — это мой собственный пользовательский класс как часть проекта :) Он не из какой-либо внешней среды.   -  person CodingBeagle    schedule 25.06.2012


Ответы (1)


Есть две возможности, если у вас есть фоновый процесс, который выполняет загрузку:

  1. Tableview является делегатом и реализует некоторую функцию uploadProgress.
  2. Табличное представление прослушивает сообщения uploadProgress NSNotifications.

Второй реализовать проще, просто поставьте слушателям start/stop в viewdidappear/viewdiddissappear. Затем при загрузке вы можете отслеживать прогресс и выдавать уведомление с прикрепленной информацией о пользователе, которая дает целочисленное значение для прогресса. В таблице есть функция, которая обрабатывает полученное уведомление и перерисовывает ячейки. Вот как добавить данные в часть userinfo NSNotification.

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


Отвратительный псевдокод, поскольку сейчас у меня нет доступа к моей среде разработки IOS.

функция загрузки:

uploadedStuff{
  upload_id = ... // unique i, maps to row in table somehow
  byteswritten = ...
  bytestotal = ....
  userinfo = new dict
  userinfo["rowid] = upload_id
  userinfo["progress"] = (int)byteswritten/bytestotal
  sendNotification("uploadprogress",userinfo)
}

таблица.м:

viewdidappear{
  listenForNotification name:"uploadprogress" handledBy:HandleUploadProgress
}

viewdiddisappear{
  stoplisteningForNotification name:"uploadprogess"
}

HandleUploadProgess:NSNotification notification {
 userinfo = [notification userinfo]
 rowId = [userinfo getkey:"rowId"]
 progress = [userinfo getkey:"rowId"]
 // update row per the link above
}
person nflacco    schedule 16.02.2012
comment
хм, кажется, это может быть возможным решением. Как именно вы обновляете информацию в одной конкретной ячейке, а затем перерисовываете ее? Я думаю, что это также момент, когда я не совсем уверен, как лучше всего справиться с этим. Я также обновил свой пост, добавив дополнительную информацию о том, как эти загружаемые объекты вызывают свои ссылающиеся элементы управления пользовательским интерфейсом. - person CodingBeagle; 16.02.2012
comment
Я добавил ссылку на объяснение того, как перерисовывать отдельные строки. Что вам нужно сделать в вашей таблице, так это иметь словарь, который сопоставляет загрузки с индексом строки таблицы. Я предполагаю, что каждая из ваших загрузок имеет уникальный идентификатор или имя, поэтому я бы использовал его. Затем в вашей функции загрузки вы хотите отправить NSNotification со словарем userinfo, содержащим две части информации: уникальный идентификатор загрузки и процент выполнения. Это уведомление обрабатывается функцией, которая распаковывает данные userinfo уведомления, а затем загружает эту конкретную строку. - person nflacco; 16.02.2012
comment
Ага, кажется, это может сработать очень хорошо :) Большое спасибо за помощь! Я попробую это. - person CodingBeagle; 16.02.2012
comment
ну, я нашел решение, которое соответствует вашей идее :) В основном я сначала создал подкласс UITableViewCell, чтобы каждая ячейка в таблице имела свойство, указывающее на действие загрузки, которое они назначают при рисовании. И затем на самом деле это те пользовательские объекты ячеек, которые прослушивают уведомления, которые выкачивают объекты активности загрузки :) Таким образом, я мог избавиться от всего сложного сопоставления. - person CodingBeagle; 17.02.2012
comment
Таким образом, я снимаю все обязанности по рисованию с объектов активности загрузки, поэтому все, что им нужно делать, — это выдавать уведомления, когда происходят важные события. Пользовательские объекты ячейки могут затем перехватывать уведомления и проверять, пришло ли это уведомление из действия загрузки, которое оно указывает на себя, а затем соответствующим образом обновлять свое собственное представление. Как вы думаете, это хорошее решение? Или можно было сделать лучше? - person CodingBeagle; 17.02.2012
comment
очень хорошо! изящнее, чем делать большую карту - person nflacco; 17.02.2012
comment
@ user1163640 не могли бы вы поделиться кодом, пожалуйста? где вы создаете и удаляете наблюдателей для ячейки? - person kain; 16.01.2013