Обновите UIProgressView на UITableViewCell
На данный момент у меня есть основное табличное представление с ячейками, которые загружаются из XML и заполняются. После этого я могу щелкнуть одну ячейку и загрузить подробный вид (файл xib, загруженный с помощью кода в основном виде таблицы). В подробном окне я могу нажать кнопку загрузки, и некоторые файлы загружаются асинхронно в папку документов. Затем я открываю вид и снова вижу свой стол.
Моя идея сейчас состоит в том, чтобы увидеть ход загрузки в ячейке таблицы. Я настроил uiprogressview для каждой ячейки, который по умолчанию скрыт. Теперь я хочу видеть индикатор выполнения при запуске загрузки. Как я могу это сделать?
Я попробовал что-то с executeSelectorOnMainThread и селектором, которые изменяют прогресс моей выбранной ячейки (которую я назначаю в основном виде таблицы). Кажется, плохая идея - не сработало.
Некоторые идеи, как это сделать?
РЕДАКТИРОВАТЬ 2: Часть кода моего решения, ВНИМАНИЕ! Это не настоящий код, я удалил много строк для вставки сюда. Есть не все релизы и т.д. Я думаю, что решение действительно грязное, но я не нашел лучшего решения для меня...
Некоторые важные вещи:
- cellDownloading: Массив, который знает каждую ячейку, которая загружается в данный момент.
- progressDictionary: знает ход каждой ячейки
- cellDictionary: знает каждую ячейку, заполненную делегатом cellForRowAtIndexpath табличного представления
Я также не могу скопировать весь код, потому что есть много вещей, которые не имеют ничего общего со всем процессом, но я даю вам важные шаги. Мои ячейки создаются путем разбора xml, поэтому у каждой ячейки есть setId в моем случае.
////////////////// // Downloader.mm ////////////////////
способ скачать асинхронный
-(void)startAsynchronousDownload:(NSString*)path{
// generate notification
NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] init];
NSNumber *tmpSetId = [NSNumber numberWithInteger:setId];
[userInfo setObject:tmpSetId forKey:@"setId"];
NSNotification* notification = [NSNotification notificationWithName:@"downloadStackNotification" object:self userInfo:userInfo];
[[NSNotificationCenter defaultCenter] postNotification:notification];
// add some infos...
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
[dictionary setObject:tmpSetId forKey:@"setId"];
// perhaps more here
// asynchronous download handling
NSOperationQueue *queue = [NSOperationQueue alloc] init];
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadImagesWithDictionary:) object:dictionary];
// release
[operation release];
[dictionary release];
[userInfo release];
}
В моем примере селектор downloadImagesWithDictionary загружает несколько изображений, для каждого загруженного изображения я отправляю уведомление. В моем случае каждая стопка изображений имеет setId.
[...]
NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] init];
NSNumber *sliceCounter = [NSNumber numberWithInt:i];
NSNumber *amount = [NSNumber numberWithInt:amountOfImages];
NSNumber *tmpSetId = [NSNumber numberWithInteger:setId];
[userInfo setObject:sliceCounter forKey:@"actualImage"];
[userInfo setObject:amount forKey:@"allImages"];
[userInfo setObject:tmpSetId forKey:@"setId"];
NSNotification* notification = [NSNotification notificationWithName:@"downloadSliceNotification" object:self userInfo:userInfo];
[[NSNotificationCenter defaultCenter] postNotification:notification ];
[...]
//////////////////////////// // TableViewController.mm ///////////////////// ///////////
Теперь нам нужно получить уведомления, чтобы обновить нашу таблицу
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(downloadSliceNotification:) name:@"downloadSliceNotification" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(downloadStackNotification:) name:@"downloadStackNotification" object:nil];
Нам нужен словарь ячеек, чтобы знать весь путь индекса существующих ячеек таблицы. Заполните их в делегате cellForRowAtIndexPath
[cellDictionary setObject:indexPath forKey:[NSString stringWithFormat:@"%d",cellSetId]];
Теперь мы создаем обработчик, который делает что-то, если мы получаем уведомление. Сначала обработчик, если загрузка начинается, у меня есть словарь прогресса, который знает каждый прогресс каждой ячейки, и я могу идентифицировать каждую ячейку по setId - возможно, вам придется немного это изменить. немного
- (void)downloadStackNotification:(NSNotification*)notification {
NSDictionary *userInfo = [notification userInfo];
NSNumber *setId = [userInfo objectForKey:@"setId"];
NSNumber *progress = [NSNumber numberWithInt:0];
[progressDictionary setObject:progress forKey:[setId stringValue]];
// add cell to downloadlist
[cellDownloading addObject:[setId stringValue]];
}
Теперь для каждого шага загрузки (в моем случае одно изображение). Рассчитать процесс и обновить словарь, получить ячейку для обновления прогресса
- (void)downloadSliceNotification:(NSNotification*)notification {
NSDictionary *userInfo = [notification userInfo];
NSNumber *sliceCounter = [userInfo objectForKey:@"actualImage"];
NSNumber *amount = [userInfo objectForKey:@"allImages"];
NSNumber *setId = [userInfo objectForKey:@"setId"];
NSNumber *progress = [NSNumber numberWithFloat:(100/[amount floatValue])*[sliceCounter floatValue]];
[progressDictionary setObject:progress forKey:[setId stringValue]];
NSIndexPath* indexPath = [cellDictionary objectForKey:[setId stringValue]];
CustomServerCell* cell = (CustomServerCell*)[self.tableView cellForRowAtIndexPath:indexPath];
NSMutableDictionary *downloadData = [[NSMutableDictionary alloc] init];
[downloadData setObject:cell forKey:@"cell"];
[downloadData setObject:sliceCounter forKey:@"actualImage"];
[downloadData setObject:amount forKey:@"allImages"];
[self performSelectorOnMainThread:@selector(updateProgressWithDictionary:) withObject:downloadData waitUntilDone:NO];
}
Обновить ячейку
-(void)updateProgressWithDictionary:(NSMutableDictionary*)downloadData {
CustomServerCell* cell = (CustomServerCell*)[downloadData objectForKey:@"cell"];
NSNumber *sliceCounter = [downloadData objectForKey:@"actualImage"];
NSNumber *amount = [downloadData objectForKey:@"allImages"];
cell.progressView.hidden = FALSE;
NSNumber *tmpProgress = [progressDictionary objectForKey:[NSString stringWithFormat:@"%d",cell.progressView.tag]];
cell.progressView.progress = [tmpProgress floatValue]/100;
cell.statusLabel.text = [NSString stringWithFormat:@"download slice %d / %d",[sliceCounter integerValue],[amount integerValue]];
}
2 ответа
Я понял проблему. Поскольку я использую tableviewcells, которые читаются из XML через Интернет, у меня были некоторые проблемы с перезагрузкой tableview. Я добился успеха в следующем процессе:
- Создать уведомление для каждого шага загрузки (в моем случае я загружаю срез за срез)
- Зарегистрировать наблюдателя в основном классе просмотра таблиц
- Создать обработчик для уведомления
- Отправить информацию о загрузке в виде словаря userinfo в уведомлении
- Сохранение прогресса каждого порядка загрузки в словаре с идентификатором в качестве ключа (в моем случае установленный идентификатор)
- Создайте селектор, прочитайте словарь и установите процесс в правой ячейке.
- Добавьте селектор в executeSelectorOnMainThread
Не знаю, если это хорошее решение - но оно работает для меня.
Попробуйте использовать
[self performSelectorOnMainThread:@selector(updateProgressBar:) withObject: [NSNumber numberWithFloat:pr] waitUntilDone: YES]
вместо
progressView.progress += 0.1; // or any other number for that matter