开发者

Update UIProgressView on UITableViewCell

开发者 https://www.devze.com 2023-03-10 10:00 出处:网络
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 tab

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:

  1. Create notification for every download step(in my case Im downloading slice per slice)
  2. Register a observer in the main tableview class
  3. Create handler for the notification
  4. Send download infos as userinfo dictionary in the notifcation
  5. Save progress of every download order in a dictionary with a identify as key(in my case a set id)
  6. Create a selector and read out the dictionary and set the process on the right cell
  7. Add the selector to the performSelectorOnMainThread

Dont know if it is a good solution - but it works for me.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号