Update UIProgressView on UITableViewCell
At the moment I got my main tableview with cells, which are loaded from a XML and filled up. After that I can click on one cell and a detailview is loaded(xib file, loaded through code in the main tableview). On the detailview I can click a download button and some files are downloaded asynchron to the documents folder. Then I pop the view down and I see again my tableview.
My idea now is to see the progress of the download in the tableview cell. I set up a uiprogressview on every cell, which is hidden on default. I now want to see the progress bar when I start the download. How can I do that?
I tried something with performSelectorOnMainThread and a selector, which change the progress of my selected cell(which I assign in the main tableview). Seems to be a bad idea - didnt work.
Some ideas how to do that?
EDIT2: Some piece of code of my solution, ATTENTION! This is not the real code, I deleted a lot of lines for inserting here. There arent all releases etc. I think the solution is really dirty, but I didnt found a better solution for me...
Some important things:
- cellDownloading: Array which knows every cell which is downloading at the moment
- progressDictionary: Knows the progress of every cell
- cellDictionary: Knows every cell, filled up in the cellsForRowAtIndexpath delegte of the tableview
I also cant copy the whole code, because there is a lot which have nothing to do with the whole process, but I give you the important steps. My cells are created through parsing a xml, so every cell has got a setId in my case.
////////////////// // Downloader.mm //////////////////
method to download asynchron
-(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];
}
In my example the selector downloadImagesWithDictionary downloads some images, for every downloaded image I send a notification. Every stack of images have a setId in my case.
[...]
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 ////////////////////////////
Now we need to get the notifications to update our tableview
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(downloadSliceNotification:) name:@"downloadSliceNotification" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(downloadStackNotification:) name:@"downloadStackNotification" object:nil];
We need a cell dictionary to know all indexpath of our existing tableview cells. Fill them in the cellForRowAtIndexPath delegate
[cellDictionary setObject:indexPath forKey:[NSString stringWithFormat:@"%d",cellSetId]];
Now we create the handler to do somehting if we got a notification First the handler if the download starts I have got a progress dictionary which knows every progress of every cell I can identify every cell by the setId - perhaps u have to change that a little bit
- (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]];
}
Now for every download step(in my case one image). Calculate process and update the dictionary, get the cell to update the progress
- (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*开发者_Python百科)[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];
}
Update the cell
-(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]];
}
Try using
[self performSelectorOnMainThread:@selector(updateProgressBar:) withObject: [NSNumber numberWithFloat:pr] waitUntilDone: YES]
instead of
progressView.progress += 0.1; // or any other number for that matter
I got the problem know. Because I use tableviewcells which are read from a XML over the internet I had some problems with the reloading of the tableview. I made know the following process to success:
- Create notification for every download step(in my case Im downloading slice per slice)
- Register a observer in the main tableview class
- Create handler for the notification
- Send download infos as userinfo dictionary in the notifcation
- Save progress of every download order in a dictionary with a identify as key(in my case a set id)
- Create a selector and read out the dictionary and set the process on the right cell
- Add the selector to the performSelectorOnMainThread
Dont know if it is a good solution - but it works for me.
精彩评论