0

I have run into an issue where having a UIProgressView as a subview of a UITableViewCell on iOS 7 makes the scrolling performance really poor. This issue doesn't really happen in iOS 6 or below and the scrolling is really great. I was wondering if I am missing something with the new UIProgressView or is it just a bug. I've seen the performance drop from like 50-60 fps to 30-40 fps when adding the UIProgressView on iOS 7. Here is some code that replicates this frame drop on iOS 7.

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if (cell == nil) {

    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

    UIProgressView *progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
    progressView.frame = CGRectMake(0, 0, cell.contentView.frame.size.width - 20, progressView.frame.size.height);
    progressView.center = CGPointMake(cell.contentView.frame.size.width/2, cell.contentView.frame.size.height/2);
    progressView.tag = 1;

    [cell.contentView addSubview:progressView];
}

UIProgressView *progressView = (UIProgressView *)[cell.contentView viewWithTag:1];
[progressView setProgress:drand48()];

// Configure the cell...

return cell;}
Pete42
  • 916
  • 7
  • 15

1 Answers1

-2

Not 100% sure if this is the issue causing what you're seeing, but your problem may lie in the fact that you are creating two UIProgressView variables there with the same name, so you could be running into a reference problem:

UIProgressView *progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
.
.
UIProgressView *progressView = (UIProgressView *)[cell.contentView viewWithTag:1];

I would personally do the following as it is a bit more of an elegant solution - subclass the cell:

.h

@interface ProgressViewCell : UITableViewCell

@property (nonatomic, retain) UIProgressView *progressView;

@end

.m

- (id)init {
    self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"ProgressViewCell"];

    self.progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
    self.progressView.frame = CGRectMake(0, 0, self.contentView.frame.size.width - 20, 44);
    self.progressView.center = CGPointMake(self.contentView.frame.size.width/2, self.contentView.frame.size.height/2);
    [self.contentView addSubview:self.progressView];

    return self;
}

And then in your tableView:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    ProgressViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ProgressViewCell"];

    if (cell == nil) {
        cell = [[ProgressViewCell alloc] init];
    }

    [cell.progressView setProgress:drand48()];

    return cell;
}
Mike
  • 9,765
  • 5
  • 34
  • 59
  • Ya in my actual code I did create a subclass of UITableViewCell but the results are the same as the code posted. Also I am not creating the UIProgressView twice. The viewWithTag function gets a reference to a pointer that already exists inside the UIView. It just searches the subviews, doesn't create them. – Pete42 Jan 10 '14 at 06:47
  • You aren't creating the progressView itself twice, but declaring the same variable name twice. Sorry, it wasn't clear, but what I meant was you are breaking best practices by "declaring a new local variable with the same name as one declared in the enclosing scope." See the section entitled "Local Variables Must Be Unique Within The Same Scope" in the following link: https://developer.apple.com/library/ios/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/Conventions/Conventions.html – Mike Jan 10 '14 at 17:27
  • Are you using a device or the simulator when experiencing those issues? I've tested the above code in both the sim and on my device and it runs fine with a few hundred cells. – Mike Jan 10 '14 at 17:30
  • @mike the progress view isn't reusable, the cell needs to implement a specific function to prevent it from showing the wrong progress. – max_ Jan 10 '14 at 17:36
  • @max_ what is the "wrong progress" here? It's not entirely clear what Pete is attempting to do here, but I assumed he wanted the progressView to change if the cell is scrolled off screen and then brought back on screen again. If this is not the intended result it would be nice to know what it is to help him achieve it. I was under the impression it was an issue with the view rendering and not the progress bar's progress. – Mike Jan 10 '14 at 17:41
  • @mike I'm referring to the `progress` property of the `progressView`. The cell needs to implement `-prepareForReuse` in order to make sure that the `progressView.progress` is set to `0` so that having the same progress on various cells will not be an issue. – max_ Jan 10 '14 at 17:43
  • @max_ sure, but I would think that was completely unrelated to the actual problem he is having, which is scrolling performance, not the progress amount itself. – Mike Jan 10 '14 at 17:45
  • My issue is that with the same code, the scrolling on ios 7 is really bad and on ios 6 it is basically 60 fps. I will look into the prepare for reuse thing but I doubt that would fix anything. My progress is always correct. The code I posted works great and as intended. this is not an issue of the progress being wrong or anything like that. The issue is the drawing of the the UIProgressView performs poorly. I was just wondering if I was doing something wrong before posting a bug report. – Pete42 Jan 10 '14 at 18:01
  • @Pete42 are you using the simulator or a real device? Like I said, my devices and simulator are working just fine with both your code and my code. If it's a real device, what model? – Mike Jan 10 '14 at 18:03
  • @pete42 you're both misunderstanding, the prepareForReuse would be an issue with Mike's code, not your original code. – max_ Jan 10 '14 at 18:06
  • @Mike the slow down happens on both the simulator and the device but it is more noticeable on the device obviously. – Pete42 Jan 10 '14 at 18:06
  • @max_ I have already implemented it a different way in my application by using a normal UIView that shows a bar with progress but it seems crazy that I would have to do that when the control exists. I am going to submit a bug report since I haven't been able to find anything that would fix this issue. – Pete42 Jan 10 '14 at 18:10