2

I need to draw a graph in a view controller. I've created a scrollview and a view as subviews of my self.view with auto layout. My data comes from an array (Core Data) that contains thousands of NSNumber. Right now, this is the code I use:

//viewController.m
@implementation viewController{
    NSArray *array;
    UIScrollView *scrollView;
    graphView *embedGraphView; //graphView is a subclass of UIView
}

- (void)viewDidLoad{
    array = @[...]; //thousand of NSNumber from Core Data Model

    //Auto layout
    scrollView = [[UIScrollView alloc] init];
    scrollView.delegate = self;
    scrollView.alwaysBounceHorizontal = YES;
    [self.view addSubview:scrollView];
    scrollView.translatesAutoresizingMaskIntoConstraints = NO;

    embedGraphView = [[graphView alloc] init];
    [embedGraphView setBackgroundColor:[UIColor whiteColor]];
    embedGraphView.array = array;
    embedGraphView.maxValue = [[array valueForKeyPath:@"@max.doubleValue"]doubleValue];
    [scrollView addSubview:embedGraphView];
    embedGraphView.translatesAutoresizingMaskIntoConstraints = NO;

    NSDictionary *metrics = @{@"width":@(array.count)};
    NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(scrollView, embedGraphView);

    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[scrollView]|" options:0 metrics:0 views:viewsDictionary]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[scrollView]|" options:0 metrics:0 views:viewsDictionary]];
    [scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[embedGraphView(width)]|" options:0 metrics:metrics views:viewsDictionary]];
    [scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[embedGraphView(scrollView)]|" options:0 metrics:0 views:viewsDictionary]];
}

//graphView.h
@interface graphView : UIView
@property (strong, nonatomic) NSArray *array;
@property double maxValue;

//graphView.m
@implementation graphView
- (void)drawRect:(CGRect)rect{
    CGContextRef ctx = UIGraphicsGetCurrentContext();  
    CGContextSetLineWidth(ctx, 0.5);
    CGContextSetStrokeColorWithColor(ctx, [[UIColor blueColor] CGColor]);
    CGContextMoveToPoint(ctx, 0, self.frame.size.height - [self.array[0]doubleValue] / self.maxValue * (self.frame.size.height-10));

    if ((float)self.array.count == self.frame.size.width){
        for (NSInteger i = 1; i < self.array.count; i++)
        {
            CGContextAddLineToPoint(ctx, i, self.frame.size.height - [self.array[i]doubleValue] / self.maxValue * (self.frame.size.height-10));
        }
    }
    CGContextDrawPath(ctx, kCGPathStroke);
}

The problem that I have is that my view controller takes several seconds before loading due to the for loop in the drawRect: method. I don't want to use the viewDidAppear method to display the embedGraphView as I may also need to redraw it on iPhone rotation. What are the solutions in order to fix this problem? Can I use GCD, image caching? And how?

Thanks.

Imanou Petit
  • 89,880
  • 29
  • 256
  • 218

1 Answers1

0

You're drawing the entire graph every time drawRect: is called. Only draw the portion that falls within the bounds of the passed in rect.

bilobatum
  • 8,918
  • 6
  • 36
  • 50
  • I changed my code in `graphView.m` in order to draw only a portion of the graph that falls within the screen bounds. In order to update my draw, I added `[embedGraphView setNeedsDisplay];` inside the `scrollViewDidScroll:` method in `viewController.m`. However, the result is not perfect: the view controller loads fast but the scrolling of the graph is now sluggish... – Imanou Petit Feb 24 '14 at 11:48