0

I have a prototype cell on an iOS storyboard that includes a UIProgressView.

A background process that executes periodically notifies a delegate that it has started. This delegate should make the UIProgressView visible on the table cell, but this is not happening. Even though I can see the delegate being called it is not causing the UIProgressView to appear.

The delegate method tries to get a pointer to the UIProgressView like this:

  UIProgressView* view = (UIProgressView*) [[[self tableView:myTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]] contentView] viewWithTag:MyProgressViewTag];

Where viewWithTag is set to the tag of the UIProgressView.

I have tried calling [myTableView reloadData] and [myTableView setNeedsDisplay] to try and force the redraw of the cell, but it has not worked.

Any ideas?

Lorenzo B
  • 33,216
  • 24
  • 116
  • 190
Jonathan Smith
  • 2,390
  • 1
  • 34
  • 60
  • All actions with UI in backgrouds should performs on main thread. – NeverBe Feb 23 '12 at 17:59
  • Thanks for all the responses. It has given me plenty to look into. However a colleague has just pointed out that another UIProgressView which is outside of the UITableView (it just sits at the top of the view) is also being updated by the background process, but that IS being updated. I'll review my code in the morning. – Jonathan Smith Feb 23 '12 at 19:56

3 Answers3

3

you request a new cell from the datasource of the tableView, the cell you get is not part of the tableView.

You want a cell that is already in the tableview, so ask the tableView for that cell.

try this:

UIProgressView* view = (UIProgressView*) [[[myTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]] contentView] viewWithTag:MyProgressViewTag];

And make sure you call this from the mainThread. You can't manipulate UI objects from a thread that is not the main thread.

Matthias Bauch
  • 89,811
  • 20
  • 225
  • 247
1

Try:

[myTableView performSelectorOnMainThread:@selector(reloadData) withObject:nil];

All UI actions must be performed on the Main Thread.

Hope it helps.

Raphael Ayres
  • 864
  • 6
  • 16
1

just a guess, but if your background process is running on something other than the main thread, the UI will not be updated. All calls to UIKit need to be made on the main thread. What you can do is use Grand Central Dispatch (GCD) and dispatch a block to the main queue. i.e. within your background process where you need to update the UIProgressView.

dispatch_async(dispatch_get_main_queue(),^{
      // your background processes call to the delegate method
});

this project shows how to update a UIProgressView from a background process using GCD: https://github.com/toolmanGitHub/BDHoverViewController

Here is another example:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0),^{
        NSInteger iCntr=0;
        for (iCntr=0; iCntr<1000000000; iCntr++) {
            if ((iCntr % 1000)==0) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    [blockSelf.hoverViewController updateHoverViewStatus:[NSString stringWithFormat:@"Value:  %f",iCntr/1000000000.0]
                                                           progressValue:(float)iCntr/1000000000.0];
                });
            }

        }

Good luck.

Tim

timthetoolman
  • 4,613
  • 1
  • 22
  • 22